题目:https://www.luogu.org/problemnew/show/P4145
题解:发现1e12开方6次就变成1了。1不管开方多少次还是1。
所以并查集记录nxt表示下一个可操作者在哪。总共操作6n次。
树状数组维护变化值,辅以原数组前缀和,轻松出答案~
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int N=100005; int n,m,l,r,nxt[N]; ll a[N],f[N],s[N]; bool b; int find(int a) { if(nxt[a]==a)return a; return nxt[a]=find(nxt[a]); } void fix(int x,ll c) { if(!c)return; for(;x<=n;x+=(x&-x))f[x]-=c; } ll query(int x) { ll ret=s[x]; for(;x;x-=(x&-x))ret+=f[x]; return ret; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); nxt[i]=i;s[i]=s[i-1]+a[i]; } scanf("%d",&m); while(m--) { scanf("%d%d%d",&b,&l,&r); if(l>r)swap(l,r); if(!b)for(int i=find(nxt[l]);i<=r;i=max(i+1,find(nxt[i]))) { ll c=a[i]; a[i]=sqrt(a[i]); fix(i,c-a[i]); if(a[i]==1)nxt[i]=find(nxt[i+1]); } if(b)printf("%lld ",query(r)-query(l-1)); } return 0; }