hdu4348 To the moon(可持久化線段樹)

Background
To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.
The premise of To The Moon is based around a technology that allows us to permanently reconstruct the memory on dying man. In this problem, we’ll give you a chance, to implement the logic behind the scene.

You‘ve been given N integers A [1], A [2],…, A [N]. On these integers, you need to implement the following operations:

  1. C l r d: Adding a constant d for every {A i | l <= i <= r}, and increase the time stamp by 1, this is the only operation that will cause the time stamp increase.
  2. Q l r: Querying the current sum of {A i | l <= i <= r}.
  3. H l r t: Querying a history sum of {A i | l <= i <= r} in time t.
  4. B t: Back to time t. And once you decide return to a past, you can never be access to a forward edition anymore.
    … N, M ≤ 10 5, |A [i]| ≤ 10 9, 1 ≤ l ≤ r ≤ N, |d| ≤ 10 4 … the system start from time 0, and the first modification is in time 1, t ≥ 0, and won’t introduce you to a future state.
    Input
    n m
    A 1 A 2 … A n
    … (here following the m operations. )
    Output
    … (for each query, simply print the result. )
    Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

2 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1

Sample Output

4
55
9
15

0
1

題意:給四種不同操作,對於詢問操作輸出答案,可持久化線段樹的板子題把.
思路:沒啥思路,直接寫主席樹,就是會出好多bug,注意點就是:
在回到之前版本的線段樹的時候,把總結點編號也給重置一下避免mle
這雖然和線段樹的板子題有點像,但是由於是可持久化的,對於當前版本的這顆樹的查詢操作我們不能把lazy標記推下去,因爲我們如果要推下去的話,那麼我們查詢之前版本的線段樹就會出錯。因爲當前版本也許會和前面版本線段樹共享兒子,把lazy推下去改變兒子節點(設編號爲x)的值之後,就會出現查詢以前版本也查到了x結點,但是此時結點已經被後面lazy標記影響了。所以查詢的時候我們應該直接把lazy影響的值返回,比如查詢到一個區間[l,r],這個區間lazy不是0,並且查詢區間ql,qr處於這個區間中,那麼不推lazy並且又要保持值不變就只能在當前區間就返回一個和:(qr+1-ql) * lazy;
最後就還有一個莫名其妙的就是,在新建一個版本線段樹時,採用先找到更新區間然後再用pushup把父結點也更新的做法的話,就會wa,只能夠再一遍建樹的時候就把每個結點的值都維護好。沒想懂爲什麼。。。

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 100000+10;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
    int f=1,res=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
    return f*res;
}

int ls[maxn*25],cnt,rs[maxn*25],root[maxn],n,m,tim;
ll sum[maxn*25],lazy[maxn*25];
void pushup(int rt,int lchd,int rchd) {
    sum[rt] = sum[lchd] + sum[rchd];
}
int build_tree(int l,int r) {
    int rt = cnt++;lazy[rt] = 0;sum[rt] = 0;
    if(l == r) {
        ll t;
        scanf("%lld",&t);
        sum[rt] = t;
        return rt;
    }
    int mid = middle;
    ls[rt] = build_tree(l,mid);
    rs[rt] = build_tree(mid+1,r);
    pushup(rt,ls[rt],rs[rt]);
    return rt;
}
void update(int l,int r,int &now,int last,int ql,int qr,ll val) {
    now = cnt++; sum[now] = sum[last];lazy[now] = lazy[last];ls[now] = ls[last];rs[now] = rs[last];
    sum[now] += (ll)(qr + 1 - ql) * val;
    if(l == ql && r == qr) {
        lazy[now] += val;
        return ;
    }
    int mid = middle;
    if(qr <= mid) {
        update(l,mid,ls[now],ls[last],ql,qr,val);
    }else if(ql > mid ){
        update(mid+1,r,rs[now],rs[last],ql,qr,val);
    }else {
        update(l,mid,ls[now],ls[last],ql,mid,val);
        update(mid+1,r,rs[now],rs[last],mid+1,qr,val);
    }
}
ll query(int l,int r,int now,int ql,int qr) {
    if(l == ql && r == qr) {
        return sum[now];
    }
    int mid = middle;
    if(qr <= mid ) return query(l,mid,ls[now],ql,qr) + lazy[now] * (ll)(qr + 1 - ql);
    else if(ql > mid) return query(mid+1,r,rs[now],ql,qr) + lazy[now] * (ll)(qr + 1 - ql);
    else return query(l,mid,ls[now],ql,mid) + query(mid+1,r,rs[now],mid+1,qr) + lazy[now] * (ll)(qr + 1 - ql);
}
void rst() {
    cnt = 0;tim = 0;
}
int main()
{
    int cas = 0;
    while(~scanf("%d%d",&n,&m)) {
        if(cas++) printf("\n");
        rst();
        root[tim] = build_tree(1, n);
        for (int i = 1; i <= m; i++) {
            char ch;
            int l, r, t;
            ll d;
            cin >> ch;
            if (ch == 'C') {
                tim++;
                scanf("%d%d%lld", &l, &r, &d);
                update(1, n, root[tim], root[tim - 1], l, r, d);
            } else if (ch == 'Q') {
                scanf("%d%d", &l, &r);
                printf("%lld\n", query(1, n, root[tim], l, r));
            } else if (ch == 'H') {
                scanf("%d%d%d", &l, &r, &t);
                printf("%lld\n", query(1, n, root[t], l, r));
            } else if (ch == 'B') {
                scanf("%d", &t);
                tim = t;
                cnt = root[tim + 1];
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章