codevs 1082 線段樹練習 3
阿新 • • 發佈:2017-05-08
build amp 正整數 output new upd val margin r+
1082 線段樹練習 3
時間限制: 3 s 空間限制: 128000 KB 題目等級 : 大師 Master 題目描述 Description
給你N個數,有兩種操作:
1:給區間[a,b]的所有數增加X
2:詢問區間[a,b]的數的和。
第一行一個正整數n,接下來n行n個整數,
再接下來一個正整數Q,每行表示操作的個數,
如果第一個數是1,後接3個正整數,
表示在區間[a,b]內每個數增加X,如果是2,
表示操作2詢問區間[a,b]的和是多少。
pascal選手請不要使用readln讀入
輸出描述 Output Description對於每個詢問輸出一行一個答案
樣例輸入 Sample Input3
1
2
3
2
1 2 3 2
2 2 3
樣例輸出 Sample Output9
數據範圍及提示 Data Size & Hint數據範圍
1<=n<=200000
1<=q<=200000
這題需要開long long,函數也要開!坑
1 //s d s 2 #include<cstdio> 3 #include<iostream> 4 #include<cstdlib> 5 using namespace std; 6 const int N=5000006; 7 long long a[N],sum[N];int miku[N]; 8 long long b,c,d,e; 9 10 void update(int rt) 11 { 12 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 13 } 14 15 void build(int l,int r,int rt) 16 { 17 if(l==r) 18 { 19 sum[rt]=a[l]; 20 return ; 21 } 22 int m=(l+r)>>1; 23 build(l,m,rt<<1); 24 build(m+1,r,rt<<1|1); 25 update(rt); 26 } 27 28 void midify_interval(int l,int r,int rt,int nowl,int nowr,int neww) 29 { 30 if(nowl==l&&nowr==r) 31 { 32 miku[rt]+=neww; 33 sum[rt]+=neww*(r-l+1); 34 return ; 35 } 36 int m=(l+r)>>1; 37 sum[rt<<1]+=miku[rt]*(m-l+1); 38 sum[rt<<1|1]+=miku[rt]*(r-m); 39 miku[rt<<1]+=miku[rt]; 40 miku[rt<<1|1]+=miku[rt]; 41 miku[rt]=0; 42 if(nowr<=m) midify_interval(l,m,rt<<1,nowl,nowr,neww); 43 else if(nowl>m) midify_interval(m+1,r,rt<<1|1,nowl,nowr,neww); 44 else 45 { 46 midify_interval(l,m,rt<<1,nowl,m,neww); 47 midify_interval(m+1,r,rt<<1|1,m+1,nowr,neww); 48 } 49 update(rt); 50 } 51 52 long long query(int l,int r,int rt,int nowl,int nowr) 53 { 54 if(nowl<=l&&nowr>=r) 55 { 56 return sum[rt]; 57 } 58 int m=(r+l)>>1; 59 sum[rt<<1]+=miku[rt]*(m-l+1); 60 sum[rt<<1|1]+=miku[rt]*(r-m); 61 miku[rt<<1]+=miku[rt]; 62 miku[rt<<1|1]+=miku[rt]; 63 miku[rt]=0; 64 long long ans=0; 65 if(nowl<=m) ans+=query(l,m,rt<<1,nowl,nowr); 66 if(nowr>m)ans+=query(m+1,r,rt<<1|1,nowl,nowr); 67 return ans; 68 } 69 70 71 72 int main() 73 { 74 int n; 75 scanf("%lld",&n); 76 for(int i=1;i<=n;i++)scanf("%lld",a+i); 77 build(1,n,1); 78 int m; 79 scanf("%lld",&m); 80 81 for(int i=1;i<=m;i++) 82 { 83 scanf("%lld",&b); 84 if(b==1) 85 { 86 scanf("%lld%lld%lld",&c,&d,&e); 87 midify_interval(1,n,1,c,d,e); 88 } 89 if(b==2) 90 { 91 scanf("%lld%lld",&c,&d); 92 printf("%lld\n",query(1,n,1,c,d)); 93 } 94 } 95 return 0; 96 97 }
codevs 1082 線段樹練習 3