poj3468 线段树区间更新,区间求和

题目链接:http://poj.org/problem?id=3468



#include 
#include
#define   LL long long int
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=2e5;
LL sum[maxn<<2],col[maxn<<2];
void Pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
    col[rt]=0;
    if(l==r)
    {
        scanf("%lld",&sum[rt]);
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    Pushup(rt);
}
void Pushdown(int rt,int len)
{
    if(col[rt])
    {
        col[rt<<1]+=col[rt]; //可能还有之前没有更新的所以用+=
        col[rt<<1|1]+=col[rt];
        sum[rt<<1]+=(len-(len>>1))*col[rt]; //这里是更新区间增加col[rt]的,所以乘的是col[rt]
        sum[rt<<1|1]+=(len>>1)*col[rt];
        col[rt]=0;
    }
}
void update(int v,int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        sum[rt]+=(LL)(r-l+1)*v;
        col[rt]+=v;
        return ;
    }
    Pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(L<=m)update(v,L,R,lson);
    if(R>m)update(v,L,R,rson);
    Pushup(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
 if(L<=l&&R>=r)
 {
     return sum[rt];
 }
  Pushdown(rt,r-l+1);
 LL ret=0;
 int m=(l+r)>>1;
 if(L<=m)ret+=query(L,R,lson);
 if(R>m)ret+=query(L,R,rson);
 return ret;
}

int main()
{
    int n,k,i,a,b,c;
    char op[10];
    while(~scanf("%d %d",&n,&k)&&n)
    {
        build(1,n,1);
        while(k--)
        {
           scanf("%s",op);
           if(op[0]=='Q')
           {
               scanf("%d %d",&a,&b);
               printf("%lld\n",query(a,b,1,n,1));
           }
           else
           {
               scanf("%d %d %d",&a,&b,&c);
               update(c,a,b,1,n,1);
           }
        }
    }
    return 0;
}


你可能感兴趣的:(线段树)