luogu 4145 花神游历各国 线段树/树状数组+并查集
此题一看便是RMQ问题,但是由于开平方的特殊操作,tag操作失效
此时发现特性:sqrt最多执行6此便使值到达1/0,此时可以剪枝不进行该操作,利用并查集到达特性找根,根代表还可以进行操作的点,再利用树状数组简单的操作便可以AC
#include<bits/stdc++.h> #define rep(i,x,y) for(register ll i=x;i<=y;i++) #define ll long long using namespace std; const ll N=100500; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;}ll k,fa[N],n,m,a[N],c[N]; inline ll lowbit(ll x){return x&(-x);} inline void add(ll x,ll d){while(x<=n){c[x]+=d;x+=lowbit(x);};} inline ll query(ll x){ll ans=0;while(x){ans+=c[x];x-=lowbit(x);};return ans;} inline ll find(ll x){return fa[x]==x?x:fa[x]=find(fa[x]);} int main(){ freopen("3038.in","r",stdin); freopen("3038.out","w",stdout); n=read();rep(i,1,n) a[i]=read(),add(i,a[i]),fa[i]=i;fa[n+1]=n+1; m=read();rep(i,1,m){ ll q=read(),l=read(),r=read(); if(l>r) swap(l,r); if(q==1) printf("%lld\n",query(r)-query(l-1)); else for(ll j=find(l);j<=r;j=find(j+1)){ ll t=sqrt(a[j]);add(j,t-a[j]);a[j]=t; if(a[j]<=1) fa[j]=find(j+1);} }return 0; }