You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
1 #include <iostream> 2 //#include<bits/stdc++.h> 3 #include <stack> 4 #include <queue> 5 #include <cstdio> 6 #include <cstring> 7 #include <algorithm> 8 using namespace std; 9 typedef long long ll; 10 typedef unsigned long long ull; 11 const int MAX=1e5+5; 12 struct node 13 { 14 int left,right,mid; 15 ll sum; 16 ll lazy; 17 }st[10*MAX]; 18 void pushup(int k)//向上刷新 19 { 20 st[k].sum=st[2*k].sum+st[2*k+1].sum; 21 } 22 void init(int l,int r,int k)//比较好的初始数据方式 23 { 24 st[k].left=l; 25 st[k].right=r; 26 st[k].mid=(l+r)/2; 27 st[k].sum=st[k].lazy=0; 28 if(l+1==r) 29 { 30 scanf("%I64d",&st[k].sum); 31 return; 32 } 33 init(l,(l+r)/2,2*k); 34 init((l+r)/2,r,2*k+1); 35 pushup(k); 36 } 37 void pushdown(int k)//向下刷新 38 { 39 if(st[k].lazy!=0) 40 { 41 st[2*k].lazy+=st[k].lazy; 42 st[2*k+1].lazy+=st[k].lazy; 43 st[2*k].sum+=(st[2*k].right-st[2*k].left)*st[k].lazy; 44 st[2*k+1].sum+=(st[2*k+1].right-st[2*k+1].left)*st[k].lazy; 45 st[k].lazy=0; 46 } 47 } 48 void update(int l,int r,int c,int k)//[l,r]区间加c 49 { 50 if(st[k].left>=r||st[k].right<=l) 51 return; 52 if(st[k].left>=l&&st[k].right<=r) 53 { 54 st[k].sum+=(st[k].right-st[k].left)*c; 55 st[k].lazy+=c; 56 return; 57 } 58 pushdown(k); 59 update(l,r,c,2*k); 60 update(l,r,c,2*k+1); 61 st[k].sum=st[2*k].sum+st[2*k+1].sum; 62 return; 63 } 64 ll query(int trl,int trr,int ptl,int ptr,int k)//询问[trl,trr]区间和的函数 65 { 66 if(ptr<=trl||ptl>=trr) 67 return 0; 68 if(ptl+1==ptr||(ptl>=trl&&ptr<=trr)) 69 return st[k].sum; 70 71 pushdown(k); 72 if(ptl>=trl&&ptr<=trr) 73 return st[k].sum; 74 return query(trl,trr,ptl,(ptl+ptr)/2,2*k)+query(trl,trr,(ptl+ptr)/2,ptr,2*k+1); 75 } 76 char tem[10]; 77 int main() 78 { 79 int n,q; 80 scanf("%d %d",&n,&q); 81 init(1,n+1,1); 82 int i,j,z; 83 while(q--) 84 { 85 scanf("%s %d %d",tem,&i,&j); 86 if(tem[0]=='Q') 87 printf("%I64d ",query(i,j+1,1,n+1,1)); 88 else 89 { 90 scanf("%d",&z); 91 update(i,j+1,z,1); 92 } 93 } 94 }
UPD.
2017.5.22
学习BIT时再做此题,用线段树重新写了一遍
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <queue> 8 #include <set> 9 #include <map> 10 #include <list> 11 #include <vector> 12 #include <stack> 13 #define mp make_pair 14 #define MIN(a,b) (a>b?b:a) 15 //#define MAX(a,b) (a>b?a:b) 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int MAX=1e5+5; 19 const int INF=1e9+5; 20 const double M=4e18; 21 using namespace std; 22 const int MOD=1e9+7; 23 typedef pair<int,int> pii; 24 const double eps=0.000000001; 25 ll lazy[MAX<<2],he[MAX<<2]; 26 char opt[50]; 27 int n,q; 28 int lo1,lo2,zhi; 29 void init(int l,int r,int k) 30 { 31 if(l==r) 32 { 33 lazy[k]=0; 34 scanf("%lld",&he[k]); 35 return; 36 } 37 int mid=(l+r)/2; 38 init(l,mid,2*k); 39 init(mid+1,r,2*k+1); 40 he[k]=he[2*k]+he[2*k+1]; 41 } 42 void add(int l,int r,int al,int ar,int k,int num) 43 { 44 if(l>=al&&r<=ar) 45 { 46 // he[k]+=(ll)(r-l+1)*num; 47 lazy[k]+=num; 48 return; 49 } 50 int mid=(l+r)/2; 51 he[k]+=(ll)(min(r,ar)-max(l,al)+1)*num; 52 if(ar<=mid) 53 add(l,mid,al,ar,2*k,num); 54 else if(al>mid) 55 add(mid+1,r,al,ar,2*k+1,num); 56 else 57 { 58 add(l,mid,al,ar,2*k,num); 59 add(mid+1,r,al,ar,2*k+1,num); 60 } 61 } 62 ll query(int l,int r,int ql,int qr,int k) 63 { 64 if(r<ql||l>qr) 65 return 0; 66 if(l>=ql&&r<=qr) 67 return he[k]+lazy[k]*(r-l+1); 68 else 69 { 70 int mid=(l+r)/2; 71 ll re=(min(qr,r)-max(ql,l)+1)*lazy[k]; 72 // re+=query(l,mid,ql,qr,2*k); 73 // re+=query(mid+1,r,ql,qr,2*k+1); 74 if(qr<=mid) 75 re+=query(l,mid,ql,qr,2*k); 76 else if(ql>mid) 77 re+=query(mid+1,r,ql,qr,2*k+1); 78 else 79 { 80 re+=query(l,mid,ql,qr,2*k); 81 re+=query(mid+1,r,ql,qr,2*k+1); 82 } 83 return re; 84 } 85 } 86 int main() 87 { 88 scanf("%d%d",&n,&q); 89 init(1,n,1); 90 while(q--) 91 { 92 scanf("%s",opt); 93 if(opt[0]=='Q') 94 { 95 scanf("%d%d",&lo1,&lo2); 96 printf("%lld ",query(1,n,lo1,lo2,1)); 97 } 98 else 99 { 100 scanf("%d%d%d",&lo1,&lo2,&zhi); 101 add(1,n,lo1,lo2,1,zhi); 102 } 103 } 104 return 0; 105 }
使用树状数组的做法:
由于树状数组一般表示”前缀和“含义的量,为了方便表示某一区间的情况,建立两个数组,分别记录add操作(区间更新)加上的值(记为数组lazy),和原本数值之和(记为数组he)。
add操作[l,r]加a时,lazy数组l位置加上a,r+1位置加上-a。he数组,l位置加上-a(l-1),r位置加上ar即可
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <queue> 8 #include <set> 9 #include <map> 10 #include <list> 11 #include <vector> 12 #include <stack> 13 #define mp make_pair 14 #define MIN(a,b) (a>b?b:a) 15 //#define MAX(a,b) (a>b?a:b) 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int MAX=1e5+5; 19 const int INF=1e9+5; 20 const double M=4e18; 21 using namespace std; 22 const int MOD=1e9+7; 23 typedef pair<int,int> pii; 24 const double eps=0.000000001; 25 char opt[50]; 26 ll he[MAX],lazy[MAX]; 27 int n,q; 28 int tem; 29 int lo1,lo2,zhi; 30 ll sum(ll *b,int i) 31 { 32 ll re=0; 33 while(i>0) 34 { 35 re+=b[i]; 36 i-=i&-i; 37 } 38 return re; 39 } 40 void add(ll *b,int i,ll val) 41 { 42 while(i<=n) 43 { 44 b[i]+=val; 45 i+=i&-i; 46 } 47 } 48 int main() 49 { 50 scanf("%d%d",&n,&q); 51 for(int i=1;i<=n;i++) 52 { 53 scanf("%d",&tem); 54 add(he,i,tem); 55 } 56 while(q--) 57 { 58 scanf("%s",opt); 59 if(opt[0]=='C') 60 { 61 scanf("%d%d%d",&lo1,&lo2,&zhi); 62 add(lazy,lo1,zhi); 63 add(he,lo1,-(ll)(zhi)*(lo1-1)); 64 add(lazy,lo2+1,-zhi); 65 add(he,lo2+1,(ll)zhi*lo2); 66 } 67 else 68 { 69 scanf("%d%d",&lo1,&lo2); 70 ll an=0; 71 an+=sum(he,lo2)+sum(lazy,lo2)*lo2; 72 an-=sum(he,lo1-1)+sum(lazy,lo1-1)*(lo1-1); 73 printf("%lld ",an); 74 } 75 } 76 return 0; 77 }