hdu4348 To the moon (segment tree may be persistent)

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

Meaning of the questions: to four different operations for the answer asks the operator output can be persistent segment tree of questions to the board.
Ideas: nothing thinking, write directly to the Chairman of the tree, that will be a lot of bug, pay attention to the point is this:
before returning to version of the tree line when the summary numbers also point to reset it to avoid mle
this board and although the title a bit like tree line, but due to be persistent, to query the current version of the tree that we can not put lazy mark pushed down, because if we want to push down, then we query the previous version of the segment tree will be wrong. Because the current version and the previous version may be shared tree line son, pushed down the lazy son changed node (set number x) value after, there will also be found in the previous version of the query x node, but this time the node has been mark behind lazy affected. So the query when we should directly affect the value of lazy return, such as a query to the interval [l, r], this interval lazy is not zero, and the query interval ql, qr in this interval, then do not push lazy and have to remain constant value and can only be returned in a current range: (qr + 1-ql) * lazy;
and finally there is a baffling is that when a new version of the tree line, find the update interval using the first and then use the pushup the parent node is also updated approach, it would wa, only then can again put the achievements of the time value of each node maintains good. I thought to understand why. . .

#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;
}
Published 33 original articles · won praise 14 · views 410

Guess you like

Origin blog.csdn.net/qq_44077455/article/details/103994995