poj 3468 A Simple Problem with Integers(线段树+延迟标记)

来源:互联网 发布:网络咨询大病种的方法 编辑:程序博客网 时间:2024/06/05 00:55

Description

You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+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

The sums may exceed the range of 32-bit integers.

Source

POJ Monthly--2007.11.25, Yang Yi


题意:
Q是询问区间和,C是在区间内每个节点加上一个值;
思路:明显的线段树,只是在更新的时候如果更新到叶子节点会超时,所以要用到延迟标记,即如果更新到某一个区间,我们用一个变量add记录此区间的增量,无需往下继续更新,当以后再次访问此区间时,如果要访问改区间的子区间,我们再往下更新,如此可以节省好多时间;
代码:
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int N=100005;struct node{    int l,r;    __int64 w,add;}str[3*N];void build(int l,int r,int n){    str[n].l=l;    str[n].r=r;    str[n].add=0;    if(l==r)    {        scanf("%I64d",&str[n].w);        return;    }    int temp=(l+r)/2;    build(l,temp,2*n);    build(temp+1,r,2*n+1);    str[n].w=str[2*n].w+str[2*n+1].w;}void push(int n){    int temp=(str[n].l+str[n].r)/2;    str[2*n].add+=str[n].add;    str[2*n+1].add+=str[n].add;    str[2*n].w+=(str[n].add)*(temp-str[2*n].l+1);    str[2*n+1].w+=str[n].add*(str[n].r-temp);    str[n].add=0;}__int64 query(int l,int r,int n){    if(str[n].l==l&&str[n].r==r)        return str[n].w;    if(str[n].add)        push(n);    int temp=(str[n].l+str[n].r)/2;    if(r<=temp)        return query(l,r,2*n);    else if(l>temp)        return query(l,r,2*n+1);    else        return query(l,temp,2*n)+query(temp+1,r,2*n+1);}void update(int l,int r,int w,int n){    if(str[n].l==l&&str[n].r==r)    {        str[n].w+=w*(r-l+1);        str[n].add+=w;        return;    }    if(str[n].add)       push(n);    int temp=(str[n].l+str[n].r)/2;    if(r<=temp)        update(l,r,w,2*n);    else if(l>temp)        update(l,r,w,2*n+1);    else    {        update(l,temp,w,2*n);        update(temp+1,r,w,2*n+1);    }    str[n].w=str[2*n].w+str[2*n+1].w;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        build(1,n,1);        char c[10];        while(m--)        {            scanf("%s",c);            if(c[0]=='Q')            {                int a,b;                scanf("%d%d",&a,&b);                printf("%I64d\n",query(a,b,1));            }            else            {                int a,b,w;                scanf("%d%d%d",&a,&b,&w);                update(a,b,w,1);            }        }    }}


0 0