您的位置:首页 > 其它

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
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: