可莉线段树
这里作者幽默的用可莉的炸弹形容可以分裂合并的线段树空间巨大,令人忍俊不禁。
#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
using namespace std;
using ll = long long;
const int MaxN = 2e5 + 10, MaxM = MaxN << 5;
struct S {
ll w;
int l, r;
} d[MaxM];
int offline[MaxM], rt[MaxN], cnt, tot, n, m;
int newnode() {
return cnt ? offline[cnt--] : ++offline[0];
}
void gooff(int k) {
offline[++cnt] = k, d[k].l = d[k].r = d[k].w = 0;
}
void modify(int &p, int k, int w, int l = 1, int r = n) {
(p) || (p = newnode());
d[p].w += w;
if (l == r) return;
int mid = l + r >> 1;
if (k <= mid) modify(d[p].l, k, w, l, mid);
else modify(d[p].r, k, w, mid + 1, r);
}
ll query(int p, int pl, int pr, int l = 1, int r = n) {
if (pl <= l && r <= pr) return d[p].w;
if (pl > r || pr < l) return 0;
int mid = l + r >> 1;
return query(d[p].l, pl, pr, l, mid) + query(d[p].r, pl, pr, mid + 1, r);
}
int merge(int p1, int p2) {
if (!p1 || !p2) return p1 | p2;
d[p1].w += d[p2].w;
d[p1].l = merge(d[p1].l, d[p2].l);
d[p1].r = merge(d[p1].r, d[p2].r);
return gooff(p2), p1;
}
void split(int x, int &y, ll k) {
if (!x) return;
(y = newnode());
if (d[d[x].l].w < k) split(d[x].r, d[y].r, k - d[d[x].l].w);
else swap(d[x].r, d[y].r);
if (k < d[d[x].l].w) split(d[x].l, d[y].l, k);
d[y].w = d[x].w - k, d[x].w = k;
}
int kth(int p, int k, int l = 1, int r = n) {
if (l == r) return l;
int mid = l + r >> 1;
if (d[d[p].l].w >= k) return kth(d[p].l, k, l, mid);
return kth(d[p].r, k - d[d[p].l].w, mid + 1, r);
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m, tot = 1;
for (int i = 1, x; i <= n; i++) {
cin >> x, modify(rt[1], i, x);
}
for (int op, p, x, y; m; m--) {
cin >> op >> p;
if (op == 0) {
cin >> x >> y;
ll k1 = query(rt[p], 1, y), k2 = query(rt[p], x, y);
int tmp = 0;
split(rt[p], rt[++tot], k1 - k2);
split(rt[tot], tmp, k2);
rt[p] = merge(rt[p], tmp);
} else if (op == 1) {
cin >> x;
rt[p] = merge(rt[p], rt[x]);
} else if (op == 2) {
cin >> x >> y;
modify(rt[p], y, x);
} else if (op == 3) {
cin >> x >> y;
cout << query(rt[p], x, y) << '\n';
} else {
cin >> x;
if (d[rt[p]].w < x) {
cout << -1 << '\n';
} else {
cout << kth(rt[p], x) << '\n';
}
}
}
return 0;
}