BZOJ3212 Pku3468 A Simple Problem with Integers(线段树区间求和、区间加模板)

题目大意:

你有N个整数,A1,A2,.,An。你需要处理两种操作。一种操作是在给定的区间内向每个数字加上一个给定的数字。另一种是求给定区间内的数字之和。

 

题解:

线段树的基本操作。

lazy标记。

附上代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,q,a[100001];
long long sum[400001],tag[400001];
void pushup(int k)
{
    sum[k]=sum[k<<1]+sum[k<<1|1];
}
void build(int l,int r,int k)
{
    if(l==r)
    {
        sum[k]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    pushup(k);
}
void lazy(int l,int r,int k,int p)
{
    tag[k]+=p;
    sum[k]+=(r-l+1)*p;
}
void pushdown(int l,int r,int k)
{
    int mid=(l+r)>>1;
    lazy(l,mid,k<<1,tag[k]);
    lazy(mid+1,r,k<<1|1,tag[k]);
    tag[k]=0;
}
void update(int l,int r,int x,int y,int v,int k)
{
    if(x<=l&&y>=r)
    {
        sum[k]+=(r-l+1)*v;
        tag[k]+=v;
        return;
    }
    pushdown(l,r,k);
    int mid=(l+r)>>1;
    if(mid>=x)
        update(l,mid,x,y,v,k<<1);
    if(mid<y)
        update(mid+1,r,x,y,v,k<<1|1);
    pushup(k);
}
long long query(int l,int r,int x,int y,int k)
{
    if(x<=l&&y>=r)
        return sum[k];
    pushdown(l,r,k);
    int mid=(l+r)>>1;
    long long ans=0;
    if(mid>=x)
        ans+=query(l,mid,x,y,k<<1);
    if(mid<y)
        ans+=query(mid+1,r,x,y,k<<1|1);
    return ans;
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,n,1);
    for(int i=1;i<=q;i++)
    {
        char k[2];
        scanf("%s",k);
        if(k[0]=='Q')
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%lld\n",query(1,n,x,y,1));
        }
        else
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            update(1,n,x,y,z,1);
        }
    }
}

 

posted @ 2018-10-19 20:46  jiangminghong  阅读(110)  评论(0编辑  收藏  举报