如题:http://poj.org/problem?id=3468
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 68751 | Accepted: 21191 | |
Case Time Limit: 2000MS |
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
题意很简单。
这一题我已经写过了,见我上一篇:线段树懒惰标记,这里换成树状数组来做。
思路:树状数组很难高效的更新区间内的所有元素加上一个值。
设s(i):加上x前的和(1-i)。
s(i)':(1-i)加上某一个数x后的和。
若i<l
s(i)'=s(i);
l=<i=<r
s(i)'=s(i)+x*(i-l+1);
=s(i)+x*i+x*(-l+1)
r<i
s(i)'=s(i)+x*(r-l+1)
在区间[l,r]上加x就看做:
在c1数组l加上x*(-l+1).
在c1数组r+1上加x*r
在c2数组l加x
在c2数组r+1加-x
于是[1,i]区间的和就是sum(c1,i)+sum(c2,i)*i
区间[l,r]和就是sum(c1,r)+sum(c2,r)*r-sum(c1,l-1)-sum(c2,l-1)*(l-1).
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 100005
#define ll long long
int N,Q;
int lowbit(int x)
{
return x&(x^(x-1));
}
ll sum(ll *a,int i)
{
ll sum=0;
while(i>0)
{
sum+=a[i];
i-=lowbit(i);
}
return sum;
}
void add(ll * a,int i,int x)
{
while(i<=N)
{
a[i]+=x;
i+=lowbit(i);
}
}
ll C1[MAXN]={0};
ll C2[MAXN]={0};
int main()
{
// freopen("C:\\1.txt","r",stdin);
cin>>N>>Q;
int i;
for(i=1;i<=N;i++)
{
int x;
scanf("%d",&x);
add(C1,i,x);
}
getchar();
while(Q--)
{
char c;
c=getchar();
if(c=='C')
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
add(C1,l,x*(-l+1));
add(C1,r+1,x*r);
add(C2,l,x);
add(C2,r+1,-x);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
ll res=0;
res+=sum(C1,r)+sum(C2,r)*r;
res-=sum(C1,l-1)+sum(C2,l-1)*(l-1);
printf("%I64d\n",res);
}
getchar();
}
return 0;
}