poj3468(一维)(区间查询,区间修改)
A Simple Problem with Integers
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<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cmath> 5 #include<cstring> 6 const int MAXN=100007; 7 char s[20],c; 8 long long tree[MAXN*4]={0},add[MAXN*4]={0}; 9 int t,num,x,n,y,m,z,a[MAXN]={0}; 10 using namespace std; 11 void build(int l,int r,int p){ 12 if (l==r) tree[p]=a[l]; 13 else { 14 int mid=(l+r)>>1; 15 build(l,mid,p*2); 16 build(mid+1,r,p*2+1); 17 tree[p]=tree[p*2]+tree[p*2+1]; 18 } 19 } 20 long long query(int l,int r,int p,int x,int y){ 21 if (l==x&&r==y) return tree[p]+add[p]*(r-l+1); 22 else { 23 add[p*2+1]+=add[p]; 24 add[p*2]+=add[p]; 25 tree[p]+=add[p]*(r-l+1); 26 add[p]=0; 27 int mid=(l+r)>>1; 28 if (y<=mid) return query(l,mid,p*2,x,y); 29 else if(x>=mid+1) return query(mid+1,r,p*2+1,x,y); 30 else return query(l,mid,p*2,x,mid)+query(mid+1,r,p*2+1,mid+1,y); 31 } 32 } 33 void change(int l,int r,int p,int x,int y,int zhi) 34 { 35 if (l==x&&r==y) add[p]+=zhi; 36 else 37 { 38 tree[p]+=zhi*(y-x+1); 39 int mid=(l+r)>>1; 40 if (y<=mid) change(l,mid,p*2,x,y,zhi); 41 else if (x>mid) change(mid+1,r,p*2+1,x,y,zhi); 42 else 43 { 44 change(l,mid,p*2,x,mid,zhi); 45 change(mid+1,r,p*2+1,mid+1,y,zhi); 46 } 47 } 48 } 49 int main(){ 50 while (~scanf("%d%d",&n,&m)){ 51 for (int i=1;i<=n;i++) 52 scanf("%d",&a[i]); 53 build(1,n,1); 54 for (int i=1;i<=m;i++){ 55 scanf("%s%d%d",&s,&x,&y); 56 if (s[0]=='Q') printf("%lld\n",query(1,n,1,x,y)); 57 else { 58 scanf("%d",&z); 59 change(1,n,1,x,y,z); 60 } 61 } 62 } 63 }
线段树虽然简单,但是树状数组就没有这么简单了,差分思想。
转换应该在树状数组blog上已经讲过了,会在blog上持续更新,最新的理解。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define N 100007 7 using namespace std; 8 9 int n,m; 10 long long c[N],d[N]; 11 char ch[3]; 12 13 int lowbit(int x) 14 { 15 return x&(-x); 16 } 17 void change(int x,int y,int z) 18 { 19 for (int i=x;i<=n;i+=lowbit(i)) 20 c[i]+=z; 21 for (int i=y+1;i<=n;i+=lowbit(i)) 22 c[i]-=z; 23 24 for (int i=x;i<=n;i+=lowbit(i)) 25 d[i]+=(long long)z*x; 26 for (int i=y+1;i<=n;i+=lowbit(i)) 27 d[i]-=(long long)z*(y+1); 28 } 29 long long query(int x) 30 { 31 long long res=0,ans=0; 32 for (int i=x;i>=1;i-=lowbit(i)) 33 res+=c[i]; 34 ans+=res*(x+1); 35 res=0; 36 for (int i=x;i>=1;i-=lowbit(i)) 37 res+=d[i]; 38 ans-=res; 39 return ans; 40 } 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 int last=0,x,y,z; 45 for (int i=1;i<=n;i++) 46 { 47 scanf("%d",&x); 48 y=x-last; 49 change(i,n,y); 50 last=x; 51 } 52 for (int i=1;i<=m;i++) 53 { 54 scanf("%s",ch); 55 if (ch[0]=='Q') 56 { 57 scanf("%d%d",&x,&y); 58 printf("%lld\n",query(y)-query(x-1)); 59 } 60 else 61 { 62 scanf("%d%d%d",&x,&y,&z); 63 change(x,y,z); 64 } 65 } 66 }