luogu 4145 花神游历各国 线段树/树状数组+并查集

时间:2021-10-28 22:53:04

此题一看便是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=;
inline ll read(){
ll x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);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=;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,,n) a[i]=read(),add(i,a[i]),fa[i]=i;fa[n+]=n+;
m=read();rep(i,,m){
ll q=read(),l=read(),r=read();
if(l>r) swap(l,r);
if(q==) printf("%lld\n",query(r)-query(l-));
else
for(ll j=find(l);j<=r;j=find(j+)){
ll t=sqrt(a[j]);add(j,t-a[j]);a[j]=t; if(a[j]<=) fa[j]=find(j+);}
}return ;
}