hdu4348(主席树区间更新)

题解:因为该题涉及到线段树要还原回去,那么肯定用主席树的区间修改区间查询,我们更新的时候直接将该点的总和加上一个(r-l)*v;

然后查询的时候上面的lazy传递下来,然后再补上(R-L+1)*x,x = 传递下来的lazy总和

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define mes(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dec(i,a,b) for(int i = b; i >= a; i--)
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define lowbit(x) x&(-x)
typedef double db;
typedef long long int ll;
typedef pair pii;
typedef unsigned long long ull;
const ll inf = 0x3f3f3f3f;
const int mx = 1e5+5;
const int mod = 1e9+7;
const int x_move[] = {1,-1,0,0,1,1,-1,-1};
const int y_move[] = {0,0,1,-1,1,-1,1,-1};
int n,m;
struct node{
    int l,r;
    ll sum,lazy;
}T[mx<<6];
int id[mx];
int cnt;
void push_up(int rt){
    T[rt].sum = T[T[rt].l].sum+T[T[rt].r].sum;
}
void built(int &rt,int l,int r){
    rt = cnt++;
    T[rt].lazy = 0;
    if(l==r){
        scanf("%lld",&T[rt].sum);
        return;
    }
    int mid = l+r>>1;
    built(T[rt].l,l,mid);
    built(T[rt].r,mid+1,r);
    push_up(rt);
}
void update(int pre,int &rt,int L,int R,int l,int r,int c){
    rt = cnt++;
    T[rt] = T[pre];
    T[rt].sum += 1ll*(r-l+1)*c;
    if(L>=l&&R<=r){
    ///    T[rt].sum += 1ll*(R-L+1)*c;
    //    cout<>1;
    if(l>mid)    update(T[pre].r,T[rt].r,mid+1,R,l,r,c);
    else if(r<=mid)    update(T[pre].l,T[rt].l,L,mid,l,r,c);
    else{
        update(T[pre].l,T[rt].l,L,mid,l,mid,c);
        update(T[pre].r,T[rt].r,mid+1,R,mid+1,r,c);
    }
}
ll query(int rt,int L,int R,int l,int r,ll x){
    if(L>=l&&R<=r){
    //    cout<>1;
    if(l>mid) return query(T[rt].r,mid+1,R,l,r,x+T[rt].lazy);
    else if(r<=mid)    return query(T[rt].l,L,mid,l,r,x+T[rt].lazy);
    else    return query(T[rt].l,L,mid,l,mid,x+T[rt].lazy)+query(T[rt].r,mid+1,R,mid+1,r,x+T[rt].lazy);
}
int main(){
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    int t,q,ca = 1;
    while(scanf("%d%d",&n,&m)!=EOF){
        cnt = 1;
        q = 0;
        built(id[0],1,n);
        while(m--){
            char op[10];
            int l,r,d;
            scanf("%s",op);
            if(op[0]=='Q'){
                scanf("%d%d",&l,&r);
                //assert(r>=l);
                printf("%lld\n",query(id[q],1,n,l,r,0));
            }
            else if(op[0]=='H'){
                scanf("%d%d%d",&l,&r,&d);
                //assert(r>=l);
                printf("%lld\n",query(id[d],1,n,l,r,0));
            }
            else if(op[0]=='B'){
                scanf("%d",&d);
                q=d;
            }
            else{
                scanf("%d%d%d",&l,&r,&d);
                q++;
                //assert(r>=l);
                update(id[q-1],id[q],1,n,l,r,d);
            }
        }
    }
    return 0;
}

 

你可能感兴趣的:(主席树,线段树)