POJ 3468 A Simple Problem with Integers(线段树区间更新)

原题链接:传送门

题意:有n个数,m次操作。输一个字符,当字符为Q时,查询a到b的总和,为C时表示从a到b加上c。

线段树简单区间更新。


#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N = 100005;
ll num[N<<2],lazy[N<<2];

void PushUp(ll rt) {
    num[rt] = num[rt<<1] + num[rt<<1|1];
}

void PushDown(ll rt,ll len) {
    if(lazy[rt]) {
        lazy[rt<<1] += lazy[rt];        //向下传 
        lazy[rt<<1|1] += lazy[rt];
        num[rt<<1] += lazy[rt] * (len - (len>>1));  //向下更新。。
        num[rt<<1|1] += lazy[rt] * (len>>1);
        lazy[rt] = 0;   //清除标记
    }
}

void Build(ll l,ll r,ll rt) {
    lazy[rt] = 0;
    if(l == r) {
        scanf("%lld",&num[rt]);
        return ;
    }
    ll m = (r-l)/2 + l;
    Build(lson);
    Build(rson);
    PushUp(rt);
}

void Updata(ll L,ll R,ll val,ll l,ll r,ll rt) {
    if(L <= l && r <= R) {
        num[rt] += val*(r-l+1);     //加上 val*区间长度 即为num[rt]的增值
        lazy[rt] += val;     //标记 +val
        return ;
    }
    PushDown(rt,r-l+1);     //向下更新
    ll m = (r-l)/2 + l;
    if(L <= m)  Updata(L,R,val,lson);
    if(R > m)   Updata(L,R,val,rson);
    PushUp(rt);
}

ll Query(ll L,ll R,ll l,ll r,ll rt) {
    if(L <= l && r <= R) {
        return num[rt];
    }
    PushDown(rt,r-l+1);
    ll ret = 0;
    ll m = (r-l)/2 + l;
    if(L <= m)  ret += Query(L,R,lson);
    if(R > m)   ret += Query(L,R,rson);
    return ret;
}

int main() {
    ll n,m;
    scanf("%lld%lld",&n,&m);
    Build(1,n,1);

    for(int i=0; i<m; i++) {
        char ch;
        ll a,b,c;

        getchar();
        scanf("%c",&ch);

        if(ch == 'Q') {
            scanf("%lld%lld",&a,&b);
            printf("%lld\n",Query(a,b,1,n,1));
        } else {
            scanf("%lld%lld%lld",&a,&b,&c);
            Updata(a,b,c,1,n,1);
        }
    }

    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_16554583/article/details/81103052