线段树 区间开平方 区间求和
模板题目:here
题意:给了一个数组,有两种操作:0,x,y,把【x,y】之间的数都开平方;1,x,y,询问【x,y】之间的所有数的和
AC_Code:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 using namespace std; 7 typedef long long ll; 8 const int maxn = 1e5+10; 9 10 struct Tree{ 11 ll l,r,val; 12 }tree[maxn<<2]; 13 ll n,m; 14 15 void pushup(ll rt){ 16 tree[rt].val = tree[rt<<1].val + tree[rt<<1|1].val; 17 return ; 18 } 19 20 void build(ll l,ll r,ll rt=1ll){ 21 tree[rt].l=l; tree[rt].r=r; 22 tree[rt].val = 0; 23 if( l==r ){ 24 scanf("%lld",&tree[rt].val); 25 return ; 26 } 27 ll mid=(l+r)>>1; 28 build(l,mid,rt<<1); 29 build(mid+1,r,rt<<1|1); 30 pushup(rt); 31 return ; 32 } 33 34 void modify(ll x, ll y, ll rt=1ll){ 35 ll l=tree[rt].l, r=tree[rt].r; 36 if( l==r ){ 37 tree[rt].val = sqrt(tree[rt].val); 38 return ; 39 } 40 if( tree[rt].val==r-l+1 && x<=l && r<=y ) return ;//一个数最多开平方8次,所以加个剪枝,当区间和等于区间元素数时,不再递归下去 41 int mid = (l+r)>>1; 42 if( x<=mid )modify(x,y,rt<<1); 43 if( y>mid ) modify(x,y,rt<<1|1); 44 pushup(rt); 45 } 46 47 ll query(ll x,ll y,ll rt=1ll){ 48 ll l = tree[rt].l, r = tree[rt].r; 49 if( x<=l && r<=y ) return tree[rt].val; 50 ll mid=(l+r)>>1; 51 ll ans = 0; 52 if( x<=mid ) ans += query(x,y,rt<<1); 53 if( y>mid ) ans += query(x,y,rt<<1|1); 54 return ans; 55 } 56 57 int main() 58 { 59 int cas=0; 60 while( ~scanf("%lld",&n) ){ 61 build(1,n); 62 scanf("%lld",&m); 63 printf("Case #%d:\n",++cas); 64 while( m-- ){ 65 int a,b,c; scanf("%d%d%d",&a,&b,&c); 66 int x=min(b,c); 67 int y=max(b,c); 68 switch( a ){ 69 case 0: 70 modify(x,y); 71 break; 72 case 1: 73 printf("%lld\n",query(x,y)); 74 break; 75 } 76 } 77 printf("\n"); 78 } 79 return 0; 80 }