[SP11470]TTM - To the moon

To The Monn

区间加的可持久化线段树

懒标记不再适用,将标记永久化,统计答案时累加即可。

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>

using namespace std;

#define LL long long
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n")

inline int rint() {
    register int x = 0, f = 1; register char c;
    while (!isdigit(c = getchar())) if (c == '-') f = -1;
    while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
    return x * f;
}

template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }

const int maxN = 1e5 + 10, maxM = 2e7;

int n, m, now, a[maxN];
int rt[maxN], cnt;

#define ls(x) (tree[x].ls)
#define rs(x) (tree[x].rs)
struct Node {
    int ls, rs;
    LL sum, tag;
} tree[maxM];

void Build(int &x, int l, int r) {
    x = ++cnt;
    if (l == r) {
        tree[x].sum = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    Build(ls(x), l, mid); Build(rs(x), mid + 1, r);
    tree[x].sum = tree[ls(x)].sum + tree[rs(x)].sum;
}

void Add(int last, int &x, int l, int r, int L, int R, int add) {
    tree[x = ++cnt] = tree[last];
    tree[x].sum += 1ll * (min(R, r) - max(L, l) + 1) * add;
    if (L <= l and r <= R) {
        tree[x].tag += add;
        return; 
    }
    int mid = (l + r) >> 1;
    if (L <= mid) Add(ls(last), ls(x), l, mid, L, R, add);
    if (mid < R) Add(rs(last), rs(x), mid + 1, r, L, R, add); 
}

LL query(int x, int l, int r, int L, int R) {
    if (L <= l and r <= R)
        return tree[x].sum;
    int mid = (l + r) >> 1;
    LL res = 0;
    if (L <= mid) res += query(ls(x), l, mid, L, R);
    if (mid < R) res += query(rs(x), mid + 1, r, L, R);
    return res + 1ll * tree[x].tag * (min(R, r) - max(L, l) + 1); 
}

signed main() {
   n = rint(), m = rint();
    for (int i = 1; i <= n; ++ i) a[i] = rint();
    Build(rt[0], 1, n);
    char op[30];
    int a, b, c;
    while (m--) {
        scanf("%s", op);
        switch(op[0]) {
        case 'C' :
            a = rint(), b = rint(), c = rint(); now++;
            Add(rt[now-1], rt[now], 1, n, a, b, c); break;
        case 'Q' :
            a = rint(), b = rint();
            printf("%lld\n", query(rt[now], 1, n, a, b)); break;
        case 'H' :
            a = rint(), b = rint(), c = rint();
            printf("%lld\n", query(rt[c], 1, n, a, b)); break;
        case 'B' :
            now = rint(); break;
        }
    }
}
posted @ 2019-03-21 21:20  茶Tea  阅读(179)  评论(0编辑  收藏  举报