Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 46811 | Accepted: 13727 | |
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 51 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
455
9
15
Hint
The sums may exceed the range of 32-bit integers.
分析:要用到一个叫懒惰标记的东东。。。就是线段树结构体里的add。。。它的作用是每次必更新到叶子结点,充分发挥线段树的优势。。。。。详见代码。有注释的。。
代码:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100000;
int a[maxn];
struct tree
{
int l;
int r;
LL add;//传说中的懒惰标记;
LL sum;
}T[maxn<<2];
void pushup(int u)
{
T[u].sum=T[u<<1].sum+T[u<<1|1].sum;
}
void pushdown(int u)
{
if(T[u].add)
{
T[u<<1].sum+=T[u].add*(T[u<<1].r-T[u<<1].l+1);
T[u<<1|1].sum+=T[u].add*(T[u<<1|1].r-T[u<<1|1].l+1);
T[u<<1].add+=T[u].add;//更新下一层节点的延迟标记
T[u<<1|1].add+=T[u].add;
T[u].add=0;//因为这时u的两个孩子都已经更新过了,所以原来的延迟标记取消了
}
}
void build(int l,int r,int u)
{
T[u].l=l;
T[u].r=r;
T[u].add=0;
if(l==r)//该区间只有一个元素;
{
T[u].sum=a[l];//这时该区间的sum即为原始数据中的值
return;
}
int mid=(T[u].l+T[u].r)>>1;
build(l,mid,u<<1);
build(mid+1,r,u<<1|1);
pushup(u);
}
void update(int l,int r,int u,int value)//在l~r区间内加上value;
{
if(l<=T[u].l&&r>=T[u].r)//采用懒惰标记的方法;
{
T[u].sum+=(LL)value*(T[u].r-T[u].l+1);
T[u].add+=value;
return;
}
pushdown(u);//如果这一层已经不能满足了,将延迟标记更新到下一层(即保证下一层的值是最新的)
int mid=(T[u].l+T[u].r)>>1;
if(r<=mid)
update(l,r,u<<1,value);
else if(l>mid)
update(l,r,u<<1|1,value);
else
{
update(l,mid,u<<1,value);
update(mid+1,r,u<<1|1,value);
}
pushup(u);
}
LL query(int l,int r,int u)
{
if(l<=T[u].l&&r>=T[u].r)//如果查询区间包含该点的区间
{
return T[u].sum;
}
int mid=(T[u].l+T[u].r)>>1;
pushdown(u);
if(r<=mid)
return query(l,r,u<<1);
else if(l>mid)
return query(l,r,u<<1|1);
else
return query(l,mid,u<<1)+query(mid+1,r,u<<1|1);
}
int main()
{
char pt[2];
int l,r,k;
int m,n,i;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
for(i=1;i<=m;i++)
{
scanf("%s",pt);
if(!strcmp(pt,"Q"))
{
scanf("%d%d",&l,&r);
printf("%lld\n",query(l,r,1));
}
else
{
scanf("%d%d%d",&l,&r,&k);
update(l,r,1,k);
}
}
return 0;
}