POJ 3468 线段树区间更新

参考:poj3468(线段树区间更新&区间求和模板)

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

题意: 输入 n, m表初始有 n 个数, 接下来 m 行输入, Q x y 表示询问区间 [x, y]的和;

         C x y z 表示区间 [x, y] 内所有数加上 z ;

AC_code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
#include<cstdlib>
#define ll long long
#define inf 0x3f3f3f3f//1e9+6e7
#define N 100010
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"**"<<endl
#define lson rt<<1
#define rson rt<<1|1
const double pi=acos(-1.0);
using namespace std;

ll sum[N<<2],add[N<<2];
int a[N];
int n;

void push_up(int rt)    //向上更新
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void push_down(int rt,int m)
{
    if(add[rt]) //若有标记,则将标记向下移动一层
    {
        add[rt<<1]+=add[rt];    //如果是更新的时候是直接修改,不是加和,此处应该为把+=改成=
        add[rt<<1|1]+=add[rt];    //修改同上
        sum[rt<<1]+=(m-(m>>1))*add[rt];    //修改同上
        sum[rt<<1|1]+=(m>>1)*add[rt];    //修改同上
        add[rt]=0;  //取消本层标记
    }
}

void build(int l,int r,int rt)  //建树
{
    add[rt]=0;
    if(l==r)
    {
        sum[rt]=a[l];
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    push_up(rt);    //向上更新
}

void update(int i,int j,ll v,int l,int r,int rt)
{
    //[i,j]是要改变的区间,[l,r]是当前正在操作的区间
    if(i <= l && j >= r)
    {
        sum[rt] += (r - l + 1) * v;//如果是更新的时候是直接修改,不是加和,此处应该为把+=改成=
        add[rt] += v;        //修改同上
        return;
    }
    push_down(rt, r - l + 1);//向下更新
    int mid = (l + r) >> 1;
    if(i <= mid) update(i, j, v, l,mid,rt<<1);
    if(j > mid) update(i, j, v, mid+1,r,rt<<1|1);
    push_up(rt);//向上更新
}

ll query(int L,int R,int l,int r,int rt)    //区间求和
{
    //[L,R]是询问的区间,[l,r]是当前正在操作的区间
    if(L<=l&&r<=R)
        return sum[rt];
    push_down(rt, r - l + 1);   //向下更新
    int m=(l+r)>>1;
    ll ans=0;
    if(L<=m) ans+=query(L,R,l,m,rt<<1);
    if(R>m) ans+=query(L,R,m+1,r,rt<<1|1);
    return ans;
}

int main()
{
    int q;
    cin>>n>>q;
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    memset(add,0,sizeof add);
    char s;
    build(1,n,1);
    int i,j;
    ll v;
    ll ans;
    while(q--)
    {
        cin>>s;
        if(s=='C')
        {
            scanf("%d%d%lld",&i,&j,&v);
            update(i,j,v,1,n,1);
        }
        if(s=='Q')
        {
            scanf("%d%d",&i,&j);
            ans=query(i,j,1,n,1);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/flyzer/article/details/82952178