1. 程式人生 > >hdu 4348 - 區間修改主席樹

hdu 4348 - 區間修改主席樹

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4348

 

題目連結:

時間倒流那肯定是主席樹啊,然後區間修改要用永久標記.下傳標記不能使用,空間會炸.

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,m,rs[30*mx],ls[30*mx];
int root[mx],tot,d;
ll sum[30*mx],add[mx*30];
void build(int l,int r,int& rt)
{
    rt = tot++;
    add[rt] = 0;
    if(l==r){
        scanf("%lld",sum+rt);
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,ls[rt]);
    build(mid+1,r,rs[rt]);
    sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}
void update(int x,int &y,int l,int r,int L,int R)
{
    y = tot++;
    rs[y] = rs[x],ls[y] = ls[x];
    sum[y] = sum[x] + 1ll*(R-L+1)*d,add[y] = add[x];
    if(L<=l&&r<=R){
        add[y] += d;
        return ;
    }
    int mid = (l+r)>>1;
    if(R<=mid) update(ls[x],ls[y],l,mid,L,R);
    else if(L>mid) update(rs[x],rs[y],mid+1,r,L,R);
    else{
        update(ls[x],ls[y],l,mid,L,mid);
        update(rs[x],rs[y],mid+1,r,mid+1,R);
    }
}
ll query(int rt,int l,int r,int L,int R,ll ad)
{
    if(L<=l&&r<=R) return sum[rt] + (r-l+1)*ad;
    int mid = (l+r)>>1;
    ll ans = 0;
    if(L<=mid) ans += query(ls[rt],l,mid,L,R,ad+add[rt]);
    if(R>mid) ans += query(rs[rt],mid+1,r,L,R,ad+add[rt]);
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        tot = 0;
        build(1,n,root[0]);
        char ch[5];
        int time = 0,L,R,t;
        while(m--){
            scanf("%s",ch);
            if(ch[0]=='C'){
                scanf("%d%d%d",&L,&R,&d);
                time++;
                update(root[time-1],root[time],1,n,L,R);
            }else if(ch[0]=='Q')
            {
                scanf("%d%d",&L,&R);
                printf("%lld\n",query(root[time],1,n,L,R,0));
            }else if(ch[0]=='H')
            {
                scanf("%d%d%d",&L,&R,&t);
                printf("%lld\n",query(root[t],1,n,L,R,0));
            }else if(ch[0]=='B'){
                scanf("%d",&t);
                time = t;
            }else while(1);
        }
    }
    return 0;
}