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
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
区间更新:
先打表ex数组 i的约数的个数
明显的看出ex[1]=1,ex[2]=2;而且不断ex[ex[i]]的过程很快会减到2或者1.
所以直接区间更新求区间和,(不用懒标记),用最大值维护一下,当该节点区间的最大值小于3,return。
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
#define maxn 1000000+100
typedef long long ll;
ll sum[maxn<<2];
ll ma[maxn<<2];
ll a[maxn];
ll ex[maxn];
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
}
void solve()
{
for(int i=1;i<maxn;i++)
{
for(int j=i;j<maxn;j+=i)
ex[j]++;
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=ma[rt]=a[l];
// printf("%d++%d\n",a[l],sum[rt]);
return ;
}
int mid=(l+r)/2;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void change(int l,int r,int rt,int L,int R)
{
if(ma[rt]<=2)
return ;
if(l==r)
{
ma[rt]=sum[rt]=ex[sum[rt]];
return ;
}
int mid=(l+r)>>1;
if(L<=mid)
change(l,mid,rt<<1,L,R);
if(R>mid)
change(mid+1,r,rt<<1|1,L,R);
pushup(rt);
}
ll query(int l,int r,int rt,int L,int R)
{
if(L<=l&&R>=r)
{
return sum[rt];
}
ll ans=0;
int mid=(l+r)/2;
if(R>mid)
ans+=query(mid+1,r,rt<<1|1,L,R);
if(L<=mid)
ans+=query(l,mid,rt<<1,L,R);
return ans;
}
int main()
{
solve();
/*for(int i=1;i<=100;i++)
cout<<ex[i]<<endl;*/
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
build(1,n,1);
while(m--)
{
int q,L,R;
scanf("%d%d%d",&q,&L,&R);
if(q==1)
{
change(1,n,1,L,R);
}
else
{
printf("%I64d\n",query(1,n,1,L,R));
}
}
return 0;
}