弱的一笔,想到这是个线段树 ,不会打表,不敢敲。知道最后变成两个就不能在减少了,这个剪枝当时没想出来,每个数都变不了几次,复杂度没仔细考虑。
#include<bits/stdc++.h>
using namespace std;
const int MAXV=1e6+5;
const int MAXN=300005;
typedef long long ll;
int d[MAXV]={0};
int a[MAXN],mx[MAXN<<2];
ll sum[MAXN<<2];
void build(int l,int r,int root)
{
if(l==r)
{
mx[root]=sum[root]=a[l];
return;
}
int m=(l+r)/2;
build(l,m,root<<1);
build(m+1,r,root*2+1);
sum[root]=sum[root<<1]+sum[root*2+1];
mx[root]=max(mx[root<<1],mx[root*2+1]);
}
void update(int l,int r,int L,int R,int root)
{
if(mx[root]<=2)return;
if(L==R)
{
mx[root]=sum[root]=d[mx[root]];
return;
}
int m=(L+R)/2;
if(m>=l)
update(l,r,L,m,root<<1);
if(m<r)update(l,r,m+1,R,root<<1|1);
sum[root]=sum[root<<1]+sum[root*2+1];
mx[root]=max(mx[root<<1],mx[root*2+1]);
}
ll query(int l,int r,int L,int R,int root)
{
if(l<=L&&r>=R)return sum[root];
int m=(L+R)/2;
ll ans=0;
if(m>=l)
ans+=query(l,r,L,m,root<<1);
if(m<r) ans+=query(l,r,m+1,R,root<<1|1);
return ans;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<MAXV;i++)
for(int j=i;j<MAXV;j+=i)
d[j]++;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
int op,l,r;
while(m--)
{
scanf("%d%d%d",&op,&l,&r);
if(op==1)update(l,r,1,n,1);
else
printf("%I64d\n",query(l,r,1,n,1));
}
return 0;
}