如题:http://poj.org/problem?id=3468
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 68742 | Accepted: 21188 | |
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
思路:懒惰标记是指每次对于一个线段树区间的更新,不用更新所有包含这个区间的子区间的区间,而是在node节点增加一个域temp,用来记录这个区间的增量,从上到下更新,当满足要加的区间l,r,tmp加上增量,区间sum更新。途中遇到有temp的区间,就把它爆破(更新sum,将temp传给他的左右区间)。最后记得要从底向上更新一遍sum。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define MAXN 100005
int N,Q;
struct node
{
int l,r;
ll temp,sum;
};
node tree[MAXN*4];
void push_up(int p)
{
tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
}
void build(int p,int l,int r)
{
tree[p].l=l;
tree[p].r=r;
tree[p].temp=0;
if(l==r)
{
scanf("%I64d",&tree[p].sum);
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
void push_down(int p)
{
if(tree[p].temp)
{
tree[p*2].temp+=tree[p].temp;
tree[p*2+1].temp+=tree[p].temp;
tree[p*2].sum+=tree[p].temp*(tree[p*2].r-tree[p*2].l+1);
tree[p*2+1].sum+=tree[p].temp*(tree[p*2+1].r-tree[p*2+1].l+1);
tree[p].temp=0;
}
}
void add(int p,int l,int r,int x)
{
if(tree[p].l==l&&tree[p].r==r)
{
tree[p].temp+=x;
tree[p].sum+=x*(r-l+1);
return;
}
push_down(p);
int mid=(tree[p].l+tree[p].r)/2;
if(l>mid)
add(p*2+1,l,r,x);
else if(r<=mid)
add(p*2,l,r,x);
else
{
add(p*2,l,mid,x);
add(p*2+1,mid+1,r,x);
}
push_up(p);
}
ll query(int p,int l,int r)
{
if(l==tree[p].l&&r==tree[p].r)
{
return tree[p].sum;
}
push_down(p);
int mid=(tree[p].l+tree[p].r)/2;
if(l>mid)
return query(p*2+1,l,r);
else if(r<=mid)
return query(p*2,l,r);
else
{
return query(p*2,l,mid)+query(p*2+1,mid+1,r);
}
}
int main()
{
freopen("C:\\1.txt","r",stdin);
cin>>N>>Q;
build(1,1,N);
getchar();
while(Q--)
{
char c;
scanf("%c",&c);
if(c=='C')
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
add(1,l,r,x);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
ll res=query(1,l,r);
printf("%I64d\n",res);
}
getchar();
}
}