HDU-4348 - To the moon (主席樹+區間修改)

Hormous的一天發表於2018-08-07

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;
            }
        }
    }
}

相關文章