Codeforces-920F:SUM and REPLACE(set+树状数组)
2018-02-03 12:40
441 查看
F. SUM and REPLACE
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Let D(x) be the number of positive divisors of a positive integer x.
For example, D(2) = 2 (2 is
divisible by 1 and 2), D(6) = 4 (6 is
divisible by 1, 2, 3 and 6).
You are given an array a of n integers.
You have to process two types of queries:
REPLACE l r —
for every
replace ai with D(ai);
SUM l r —
calculate
.
Print the answer for each SUM query.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 3·105)
— the number of elements in the array and the number of queries to process, respectively.
The second line contains n integers a1, a2,
..., an (1 ≤ ai ≤ 106)
— the elements of the array.
Then m lines follow, each containing 3 integers ti, li, ri denoting i-th
query. If ti = 1,
then i-th query is REPLACE li ri,
otherwise it's SUM liri (1 ≤ ti ≤ 2, 1 ≤ li ≤ ri ≤ n).
There is at least one SUM query.
Output
For each SUM query print the answer to it.
Example
input
output
思路:第一眼看到题目就知道是数据结构。同时也可以算出[1,1e6]的d[i],并发现每个数ai最多经过10次操1(replace ai with D(ai))就会变为1或2,即ai=D(ai)。想到思路却想不出办法处理。看到别人用set才恍然大悟。先将ai>2的i放到set中,更新的时候用二分查找所在位置,然后更新ai,更新树状数组(i,d[a[i]]-ai);如果ai<=2,就把i从set中删除。
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e6;
const int MOD=1e9+7;
typedef __int64 ll;
int a[MAX],d[MAX];
ll A[MAX];
int n,m;
set<int>p;
set<int>::iterator it;
void init()//计算D[i]
{
memset(d,0,sizeof d);
d[0]=0;
for(int i=1;i<=1e6;i++)
{
for(int j=i;j<=1e6;j+=i)d[j]++;
}
}
void add(int x,int y)
{
while(x<=n)
{
A[x]+=y;
x+=x&(-x);
}
}
ll ask(int x)
{
ll ans=0;
while(x)
{
ans+=A[x];
x-=x&(-x);
}
return ans;
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
if(a[i]>2)p.insert(i);
}
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
it=p.lower_bound(x);
while(it!=p.end()&&*it<=y)
{
int pre=a[*it],nex=d[a[*it]];
add(*it,nex-pre);//更新树状数组
a[*it]=nex;//更新a[i]
if(nex<=2)p.erase(it++);//a[i]<=2,删除
else it++;
}
}
else printf("%I64d\n",ask(y)-ask(x-1));
}
return 0;
}
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Let D(x) be the number of positive divisors of a positive integer x.
For example, D(2) = 2 (2 is
divisible by 1 and 2), D(6) = 4 (6 is
divisible by 1, 2, 3 and 6).
You are given an array a of n integers.
You have to process two types of queries:
REPLACE l r —
for every
replace ai with D(ai);
SUM l r —
calculate
.
Print the answer for each SUM query.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 3·105)
— the number of elements in the array and the number of queries to process, respectively.
The second line contains n integers a1, a2,
..., an (1 ≤ ai ≤ 106)
— the elements of the array.
Then m lines follow, each containing 3 integers ti, li, ri denoting i-th
query. If ti = 1,
then i-th query is REPLACE li ri,
otherwise it's SUM liri (1 ≤ ti ≤ 2, 1 ≤ li ≤ ri ≤ n).
There is at least one SUM query.
Output
For each SUM query print the answer to it.
Example
input
7 6 6 4 1 10 3 2 4 2 1 7 2 4 5 1 3 5 2 4 4 1 5 7 2 1 7
output
30 13 4 22
思路:第一眼看到题目就知道是数据结构。同时也可以算出[1,1e6]的d[i],并发现每个数ai最多经过10次操1(replace ai with D(ai))就会变为1或2,即ai=D(ai)。想到思路却想不出办法处理。看到别人用set才恍然大悟。先将ai>2的i放到set中,更新的时候用二分查找所在位置,然后更新ai,更新树状数组(i,d[a[i]]-ai);如果ai<=2,就把i从set中删除。
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e6;
const int MOD=1e9+7;
typedef __int64 ll;
int a[MAX],d[MAX];
ll A[MAX];
int n,m;
set<int>p;
set<int>::iterator it;
void init()//计算D[i]
{
memset(d,0,sizeof d);
d[0]=0;
for(int i=1;i<=1e6;i++)
{
for(int j=i;j<=1e6;j+=i)d[j]++;
}
}
void add(int x,int y)
{
while(x<=n)
{
A[x]+=y;
x+=x&(-x);
}
}
ll ask(int x)
{
ll ans=0;
while(x)
{
ans+=A[x];
x-=x&(-x);
}
return ans;
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
if(a[i]>2)p.insert(i);
}
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
it=p.lower_bound(x);
while(it!=p.end()&&*it<=y)
{
int pre=a[*it],nex=d[a[*it]];
add(*it,nex-pre);//更新树状数组
a[*it]=nex;//更新a[i]
if(nex<=2)p.erase(it++);//a[i]<=2,删除
else it++;
}
}
else printf("%I64d\n",ask(y)-ask(x-1));
}
return 0;
}
相关文章推荐
- Codeforces 920F - SUM and REPLACE【线段树】
- Codeforces 920F - SUM and REPLACE(线段树)
- Codeforces 920F-SUM and REPLACE
- Codeforces - 277.5 (Div. 2)C - Given Length and Sum of Digits...(模拟 or dfs)
- CodeForces 703D Mishka and Interesting sum
- Codeforces 703D Mishka and Interesting sum 树状数组
- CodeForces 703D Mishka and Interesting sum
- CodeForces - 276C Little Girl and Maximum Sum (扫描线)
- CodeForces 489C (贪心) Given Length and Sum of Digits...
- Codeforces 365Div2 D Mishka and Interesting sum
- CF EDU 37 F SUM and REPLACE 【线段树区间更新中的单点更新】 好题!
- 【codeforces 703 D】【离线询问 树状数组 前驱思想 前缀异或和】D. Mishka and Interesting sum【 区间内出现次数偶数的数的异或和】
- CodeForces - 276C Little Girl and Maximum Sum
- CodeForces 703D Mishka and Interesting sum(树状数组 区间异或)
- Codeforces 703D Mishka and Interesting sum(树状数组+扫描线)
- Educational Codeforces Round 37 (Rated for Div. 2) F. SUM and REPLACE(线段树,区间更新)
- codeforces 703D Mishka and Interesting sum (树状数组区间异或)
- Codeforces #277.5 (Div. 2) C. Given Length and Sum of Digits...(简单贪心)
- Codeforces 276C Little Girl and Maximum Sum(线段树的区间更新)
- Codeforces 489C - Given Length and Sum of Digits...(贪心)