1. 程式人生 > 實用技巧 >線段樹 區間開平方 區間求和

線段樹 區間開平方 區間求和

模板題目: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 }