首页 > 代码库 > POJ3468 A Simple Problem with Integers
POJ3468 A Simple Problem with Integers
Description
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 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4
Sample Output
455915
Hint
Source
1)令delta[s] = delta[s] + d,表示将A[s]...A[n]同时增加d,但这样A[t+1]...A[n]就多加了d,所以
2)再令delta[t+1] = delta[t+1] - d,表示将A[t+1]...A[n]同时减d
然后来看查询操作query(s, t),求A[s]...A[t]的区间和,转化为求前缀和,设sum[i] = A[1]+...+A[i],则
A[s]+...+A[t] = sum[t] - sum[s-1],
那么前缀和sum[x]又如何求呢?它由两部分组成,一是数组的原始和,二是该区间内的累计增量和, 把数组A的原始值保存在数组org中,
并且delta[i]对sum[x]的贡献值为delta[i]*(x+1-i),那么
sum[x] = org[1]+...+org[x] + delta[1]*x + delta[2]*(x-1) + delta[3]*(x-2)+...+delta[x]*1
= org[1]+...+org[x] + segma(delta[i]*(x+1-i))
= segma(org[i]) + (x+1)*segma(delta[i]) - segma(delta[i]*i),1 <= i <= x
=segma(org[i]-delta[i]*i)+(x+1)*delta[i], i<=1<=x
这其实就是三个数组org[i], delta[i]和delta[i]*i的前缀和,org[i]的前缀和保持不变,事先就可以求出来,delta[i]和delta[i]*i的前缀和是不断变化的,可以用两个树状数组来维护。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector>10 #include <queue>11 #include <map>12 #include <set>13 using namespace std;14 typedef long long LL;15 const int MAXN = 100011;16 int n,m;17 int a[MAXN];18 LL sum[MAXN],c1[MAXN],c2[MAXN],ans;19 char ch[12];20 21 inline int getint()22 {23 int w=0,q=0; char c=getchar();24 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar(); 25 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); return q ? -w : w;26 }27 28 inline void add(LL x,LL val){29 LL cun=x;30 while(x<=n) {31 c1[x]+=val; c2[x]+=val*cun;32 x+=x&(-x);33 }34 }35 36 inline LL query(LL x){37 LL total=0; LL cun=x;38 while(x>0) {39 total+=c1[x]*(cun+1)-c2[x];40 x-=x&(-x);41 }42 return total;43 }44 45 inline LL count(LL l,LL r){46 return query(r)-query(l-1);47 }48 49 inline void work(){50 n=getint(); m=getint(); for(int i=1;i<=n;i++) a[i]=getint(),sum[i]=sum[i-1]+a[i];51 int l,r; LL val;52 while(m--) {53 scanf("%s",ch); 54 if(ch[0]==‘C‘) {55 l=getint(); r=getint(); val=getint();56 add(l,val); add(r+1,-val);57 } else{58 l=getint(); r=getint();59 ans=sum[r]-sum[l-1]; ans+=count(l,r);60 printf("%lld\n",ans);61 }62 }63 }64 65 int main()66 {67 work();68 return 0;69 }
POJ3468 A Simple Problem with Integers