poj 3468 A Simple Problem with Integers 线段树

线段树的区间加减数,区间查询

#include <cstdio>
#include <algorithm>
using namespace std;
#define LL __int64
const int maxn = 100100;
LL sum[4*maxn];
LL add[4*maxn];
void build(int l,int r,int o)
{
    add[o]=0;
    if(l==r)
    {
        scanf("%I64d",&sum[o]);
        return ;
    }
    int m=(l+r)/2;
    build(l,m,2*o);
    build(m+1,r,2*o+1);
    sum[o]=sum[2*o]+sum[2*o+1];
}
void update(int ql,int qr,int z,int l,int r,int o)
{
    if(ql<=l&&r<=qr)
    {
        add[o]+=z;
        sum[o]+=(LL)z*(r-l+1);
        return ;
    }
    if(add[o])
    {
        add[2*o]+=add[o];
        add[2*o+1]+=add[o];
        sum[o*2] += add[o] * (r-l+1 - (r-l+1)/2);
		sum[o*2+1] += add[o] * ((r-l+1)/2);
		add[o]=0;
    }
    int m=(l+r)/2;
    if(ql<=m) update(ql,qr,z,l,m,2*o);
    if(qr>m) update(ql,qr,z,m+1,r,2*o+1);
    sum[o]=sum[2*o]+sum[2*o+1];
}

LL query(int ql,int qr,int l,int r,int o)
{
    if(ql<=l&&r<=qr)
        return sum[o];
    if(add[o])
    {
        add[2*o]+=add[o];
        add[2*o+1]+=add[o];
        sum[o*2] += add[o] * (r-l+1 - (r-l+1)/2);
		sum[o*2+1] += add[o] * ((r-l+1)/2);
		add[o]=0;
    }
    LL ans=0;
    int m=(l+r)/2;
    if(ql<=m) ans+=query(ql,qr,l,m,2*o);
    if(qr>m) ans+=query(ql,qr,m+1,r,2*o+1);
    return ans;
}

int main()
{
    int n,q;
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        build(1,n,1);
        char c;
        int i,j;
		int x,y,z;
		getchar();
        for(i=1;i<=q;i++)
        {
            scanf("%c",&c);
            if(c=='Q')
            {
                scanf("%d%d",&x,&y);
                printf("%I64d
",query(x,y,1,n,1));
            }
            else
            {
                scanf("%d%d%d",&x,&y,&z);
                update(x,y,z,1,n,1);
            }
			getchar();
        }
    }
    return 0;
}


 

原文地址:https://www.cnblogs.com/vermouth/p/3710161.html