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

转载于:https://www.cnblogs.com/cnyali-Tea/p/10574722.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值