BZOJ3038 上帝造题的七分钟2 线段树
一个数最多是会被开方次数不会很多,所以直接暴力修改即可.
#include <bits/stdc++.h> #define N 100005 #define ll long long #define lson now<<1 #define rson now<<1|1 #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; int n,m,tag[N<<2]; ll A[N],sum[N<<2]; void build(int l,int r,int now) { if(l==r) { sum[now]=A[l]; if(sum[now]==1ll) tag[now]=1; return; } int mid=(l+r)>>1; if(l<=mid) build(l,mid,lson); if(r>mid) build(mid+1,r,rson); sum[now]=sum[lson]+sum[rson]; if(sum[now]==r-l+1) tag[now]=1; } ll query(int l,int r,int now,int L,int R) { if(l>=L&&r<=R) return sum[now]; int mid=(l+r)>>1; ll re=0; if(L<=mid) re+=query(l,mid,lson,L,R); if(R>mid) re+=query(mid+1,r,rson,L,R); return re; } void update(int l,int r,int now,int L,int R) { if(tag[now]) return ; if(l==r) { sum[now]=(ll)sqrt(sum[now]); return; } int mid=(l+r)>>1; if(L<=mid) update(l,mid,lson,L,R); if(R>mid) update(mid+1,r,rson,L,R); sum[now]=sum[lson]+sum[rson]; if(sum[now]==r-l+1) tag[now]=1; } int main() { int i,j; // setIO("input"); scanf("%d",&n); for(i=1;i<=n;++i) scanf("%lld",&A[i]); build(1,n,1); scanf("%d",&m); for(i=1;i<=m;++i) { int op,l,r; scanf("%d%d%d",&op,&l,&r); if(l>r) swap(l,r); if(op==1) { printf("%lld\n",query(1,n,1,l,r)); } else { update(1,n,1,l,r); } } return 0; }