可莉线段树

这里作者幽默的用可莉的炸弹形容可以分裂合并的线段树空间巨大,令人忍俊不禁。

796E3BC73249DFE6C3B89BE9E0B01D61

#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;
}
posted @ 2025-08-28 16:07  yabnto  阅读(13)  评论(0)    收藏  举报