HDU-4348 - To the moon (主席树+区间修改)

To the moon

题目链接: To the moon HDU - 4348

题意

给你长度为n的数组,共有四个操作:

•1.对区间【L,R】增加d,并时间增加1

•2.询问当前时间的区间【L,R】的和

•3.询问时间为T时的区间【L,R】的和

•4.返回到时间为T的时候


思路

既然有着时间点的要求也就是历史版本的要求,那么主席树肯定是没跑的了,奈何我没有合适的模板,那么这道题,就是我主席树的模板了吧。还有但是主席树的区间的修改,一种办法是在遇到有延迟更新的区间的时候重新开左右儿子来pushdown 标记,但是这题严格一点的数据就能把他卡成空间为n*n*logn。所以还有一种办法就是,永久化标记,不pushdown,这时候就可以大大节省空间了,nlogn的空间复杂度。


代码

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const int MAXN = (int)1e5+7;
const int INF = (int)0x3f3f3f3f;

int root[MAXN*10],lc[MAXN*32],rc[MAXN*32],tot;
ll tree[MAXN*32],add[MAXN*32];
int A[MAXN];

void Build(int l,int r,int root){
    add[root] = 0;
    if(l == r) {
        tree[root] = A[l];
        return ;
    }
    int mid = l+r>>1;
    Build(l,mid,lc[root]=++tot);
    Build(mid+1,r,rc[root]=++tot);
    tree[root] = tree[lc[root]] + tree[rc[root]];
}

void Update(int last,int cur,int L,int R,int l,int r,ll d){
    tree[cur] = tree[last] + d*(min(R,r)-max(L,l)+1);
    lc[cur] = lc[last];
    rc[cur] = rc[last];
    add[cur] = add[last];
    if(L <= l && r <= R) {
        add[cur] += d;
        return ;
    }
    int mid = l+r>>1;
    if (L <= mid)Update(lc[last],lc[cur]=++tot,L,R,l,mid,d);
    if (R >  mid)Update(rc[last],rc[cur]=++tot,L,R,mid+1,r,d);
}

ll query(int cur,int L,int R,int l,int r,ll ad){
    if(L <= l && r <= R) return tree[cur]+(r-l+1)*ad;
    int mid = l+r>>1;
    ll ans = 0;
    if (L <= mid)ans += query(lc[cur],L,R,l,mid,ad+add[cur]);
    if (R >  mid)ans += query(rc[cur],L,R,mid+1,r,ad+add[cur]);
    return ans;
}

void init() {
    tot = 0;
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        init();
        rep(i,1,n) scanf("%lld",&A[i]);
        Build(1,n,root[1]=++tot);
        int time = 1;
        rep(i,1,m) {
            char op[2];int l,r,t;ll k;
            scanf("%s",op);
            if(op[0] == 'C') {
                scanf("%d %d %lld",&l,&r,&k);
                time++;
                Update(root[time-1],root[time]=++tot,l,r,1,n,k);
            }
            else if(op[0]=='Q') {
                scanf("%d %d",&l,&r);
                printf("%lld\n",query(root[time],l,r,1,n,0));
            }
            else if(op[0]=='H') {
                scanf("%d %d %d",&l,&r,&t);
                t++;
                printf("%lld\n",query(root[t],l,r,1,n,0));
            }
            else if(op[0]=='B') {
                scanf("%d",&t);
                time=t+1;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40513946/article/details/81488223