#樹狀陣列,並查集#CF920F SUM and REPLACE
阿新 • • 發佈:2020-08-19
分析
由於\(a_i=1或2\)時\(d(a_i)=a_i\),且其餘情況修改後答案只會越來越小,
考慮用樹狀陣列維護區間和,用並查集跳過\(a_i=1或2\)的情況
程式碼
#include <cstdio> #include <cctype> #define rr register using namespace std; const int N=1000011,M=300011; typedef long long lll; int n,m,a[M],f[M],Cnt; lll c[M]; int prime[M],d[N],mc[N]; bool v[N]; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void print(lll ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } inline void Pro(int n){ d[1]=1,mc[1]=1; for (rr int i=2;i<=n;++i){ if (!v[i]) prime[++Cnt]=i,d[i]=mc[i]=2; for (rr int j=1;j<=Cnt&&prime[j]<=n/i;++j){ v[i*prime[j]]=1; if (i%prime[j]==0){ mc[i*prime[j]]=mc[i]+1; d[i*prime[j]]=d[i]/mc[i]*(mc[i]+1); break; } mc[i*prime[j]]=2, d[i*prime[j]]=d[i]<<1; } } } inline signed getf(int u){return f[u]==u?u:f[u]=getf(f[u]); } inline void update(int x,int y){for (;x<=n;x+=-x&x) c[x]+=y;} inline lll query(int l,int r){ rr lll ans=0; --l; for (;r>l;r-=-r&r) ans+=c[r]; for (;l>r;l-=-l&l) ans-=c[l]; return ans; } signed main(){ n=iut(),m=iut(),Pro(N-11),f[n+1]=n+1; for (rr int i=1;i<=n;++i) c[i]=c[i-1]+(a[i]=iut()); for (rr int i=n;i;--i) f[i]=i,c[i]-=c[i&(i-1)]; for (rr int z,l,r;m;--m){ z=iut(),l=iut(),r=iut(); if (z==2) print(query(l,r)),putchar(10); else for (rr int i=getf(l);i<=r;){ update(i,d[a[i]]-a[i]),a[i]=d[a[i]]; f[i]=i+(a[i]<3),i=(getf(i)==i)?i+1:f[i]; } } return 0; }