题意:给你一段序列,然后有2种操作,0是代表吧LR区间内的数全部去根号,1是代表求和
思路:线段树维护,大那是全部为1的区间需要加特判,以及区间的左右端点需要重新判断
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=100005; LL sum[maxn<<2],as[maxn]; void build(int l,int r,int i) { if(l==r){ scanf("%lld",&sum[i]); return ; } int mid=(l+r)>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); sum[i]=sum[i<<1]+sum[i<<1|1]; } void update(int L,int R,int l,int r,int i) { if(l==r){ sum[i]=sqrt((sum[i])); return ; } if(L<=l&&r<=R&&sum[i]==r-l+1)return ; int mid=(l+r)>>1; if(L<=mid) update(L,R,l,mid,i<<1); if(R>mid) update(L,R,mid+1,r,i<<1|1); sum[i]=sum[i<<1]+sum[i<<1|1]; } LL query(int L,int R,int l,int r,int i) { if(L<=l&&r<=R) return sum[i]; int mid=(l+r)>>1; LL cnt=0; if(L<=mid) cnt+=query(L,R,l,mid,i<<1); if(R>mid) cnt+=query(L,R,mid+1,r,i<<1|1); return cnt; } int main() { int n,m,cas=1; while(~scanf("%d",&n)){ build(1,n,1); scanf("%d",&m); int a,b,c; printf("Case #%d: ",cas++); for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); int bb=min(b,c),cc=max(b,c); if(a)printf("%lld ",query(bb,cc,1,n,1)); else update(bb,cc,1,n,1); } printf(" "); } return 0; } /* 10 1 2 3 4 5 6 7 8 9 10 5 0 1 10 1 1 10 1 1 5 0 5 8 1 4 8 */