Dicription
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 li ri (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
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
30
13
4
22
可以发现每个数被改若干次之后就会变成2(或者这个数本来就为1它也只能是1),而这个次数的最大值也不会很大,所以我们就可以维护一个还没有变成≤2的位置集合,然后暴力单点修改。又因为是求前缀和,所以我们再维护一个树状数组就好了,时间复杂度O(N*log²N)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<set> #define ll long long #define maxn 300005 #define maxm 1000000 using namespace std; set<int> s; set<int> ::iterator it; int zs[maxn],t=0,low[maxm+5]; int d[maxm+5],n,m,le,ri,opt; bool v[maxm+5]; int a[maxn]; ll f[maxn],qz[maxn]; inline void init(){ d[1]=1,low[1]=1; for(int i=2;i<=maxm;i++){ if(!v[i]) zs[++t]=i,d[i]=2,low[i]=i; for(int j=1,u;j<=t&&(u=zs[j]*i)<=maxm;j++){ v[u]=1; if(!(i%zs[j])){ low[u]=low[i]*zs[j]; if(low[i]==i) d[u]=d[i]+1; else d[u]=d[low[u]]*d[i/low[i]]; break; } low[u]=zs[j],d[u]=d[i]<<1; } } } inline void update(int x,int y){ for(;x<=n;x+=x&-x) f[x]+=(ll)y; } inline ll query(ll x){ ll an=0; for(;x;x-=x&-x) an+=f[x]; return an; } inline void solve(){ int pre=*s.lower_bound(le); while(pre<=ri){ update(pre,d[a[pre]]-a[pre]); a[pre]=d[a[pre]]; if(a[pre]<=2) s.erase(pre); pre=*s.upper_bound(pre); } } int main(){ init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",a+i); qz[i]=qz[i-1]+(ll)a[i]; s.insert(i); } s.insert(n+1); while(m--){ scanf("%d%d%d",&opt,&le,&ri); if(opt==2) printf("%lld ",qz[ri]-qz[le-1]+query(ri)-query(le-1)); else solve(); } return 0; }