P5494 【模板】线段树分裂
题目链接:https://www.luogu.com.cn/problem/P5494
解题思路:来自 oi.wiki
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, maxm = maxn * 30;
long long tr[maxm];
int n, m, rt[maxm], ls[maxm], rs[maxm], idx, rub[maxm], idx2, idx3 = 1;
// idx: 新建节点个数; idx2: 垃圾站中节点个数; idx3: 可重集个数
int New() {
return idx2 ? rub[idx2--] : ++idx;
}
void Del(int &u) {
ls[u] = rs[u] = tr[u] = 0;
rub[++idx2] = u;
u = 0;
}
void push_up(int u) {
tr[u] = tr[ ls[u] ] + tr[ rs[u] ];
}
void build(int l, int r, int &u) {
if (!u)
u = New();
if (l == r) {
scanf("%lld", tr+u);
return;
}
int mid = l + r >> 1;
build(l, mid, ls[u]);
build(mid+1, r, rs[u]);
push_up(u);
}
int Merge(int l, int r, int a, int b) {
if (!a || !b) return a + b;
if (l == r) {
tr[a] += tr[b];
Del(b);
return a;
}
int mid = l + r >> 1;
ls[a] = Merge(l, mid, ls[a], ls[b]);
rs[a] = Merge(mid+1, r, rs[a], rs[b]);
Del(b);
push_up(a);
return a;
}
void Split(int L, int R, int l, int r, int &a, int &b) {
if (r < L || R < l)
return;
if (!a)
return;
if (L <= l && r <= R) {
b = a;
a = 0;
return;
}
if (!b)
b = New();
int mid = l + r >> 1;
if (L <= mid) Split(L, R, l, mid, ls[a], ls[b]);
if (R > mid) Split(L, R, mid+1, r, rs[a], rs[b]);
push_up(a);
push_up(b);
}
void add(int p, int v, int l, int r, int &u) {
if (!u)
u = New();
if (l == r) {
tr[u] += v;
return;
}
int mid = l + r >> 1;
(p <= mid) ? add(p, v, l, mid, ls[u]) : add(p, v, mid+1, r, rs[u]);
push_up(u);
}
long long query(int L, int R, int l, int r, int u) {
if (!u)
return 0;
if (L <= l && r <= R)
return tr[u];
int mid = l + r >> 1;
long long res = 0;
if (L <= mid) res += query(L, R, l, mid, ls[u]);
if (R > mid) res += query(L, R, mid+1, r, rs[u]);
return res;
}
int kth(int k, int l, int r, int u) {
if (tr[u] < k) return -1;
if (l == r)
return l;
int mid = l + r >> 1;
long long num = tr[ ls[u] ];
return (k <= num) ? kth(k, l, mid, ls[u]) : kth(k-num, mid+1, r, rs[u]);
}
int main() {
scanf("%d%d", &n, &m);
build(1, n, rt[1]);
while (m--) {
int op;
scanf("%d", &op);
if (op == 0) { // 0 p x y
int p, x, y;
scanf("%d%d%d", &p, &x, &y);
Split(x, y, 1, n, rt[p], rt[++idx3]);
}
else if (op == 1) { // 1 p t
int p, t;
scanf("%d%d", &p, &t);
rt[p] = Merge(1, n, rt[p], rt[t]);
}
else if (op == 2) { // 2 p x q
int p, x, q;
scanf("%d%d%d", &p, &x, &q);
add(q, x, 1, n, rt[p]);
}
else if (op == 3) { // 3 p x y
int p, x, y;
scanf("%d%d%d", &p, &x, &y);
long long ans = query(x, y, 1, n, rt[p]);
printf("%lld\n", ans);
}
else { // 4 p k
int p, k;
scanf("%d%d", &p, &k);
int ans = kth(k, 1, n, rt[p]);
printf("%d\n", ans);
}
}
return 0;
}
浙公网安备 33010602011771号