标签:
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 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
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
标签:
原文地址:http://www.cnblogs.com/ljh2000-jump/p/5866269.html