学习知识来自AGOH的B站视频
银酱对线段树合并空间大小的计算
模板题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
struct node {
int l, r;
ll val;
}sgt[(maxn+10) * 40];
int cnt, root[maxn+10];
int n, m;
void pushup(int rt) {
sgt[rt].val = sgt[sgt[rt].l].val + sgt[sgt[rt].r].val;
}
void modify(int &rt, int l, int r, int pos, int x) {
if(!rt) rt = ++ cnt;
sgt[rt].val += x;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) modify(sgt[rt].l,l,mid,pos,x);
if(pos > mid) modify(sgt[rt].r,mid+1,r,pos,x);
}
int split(int &rt, int l, int r, int posl, int posr) {
int now = ++ cnt;
if(posl <= l && posr >= r) {
sgt[now] = sgt[rt];
rt = 0;
} else {
int mid = (l + r) >> 1;
if(posl <= mid) sgt[now].l = split(sgt[rt].l,l,mid,posl,posr);
if(posr > mid) sgt[now].r = split(sgt[rt].r,mid+1,r,posl,posr);
pushup(now);
pushup(rt);
}
return now;
}
ll ask(int rt, int l, int r, int posl, int posr) {
if(posl <= l && posr >= r) return sgt[rt].val;
ll sum = 0;
int mid = (l + r) >> 1;
if(posl <= mid) sum += ask(sgt[rt].l,l,mid,posl,posr);
if(posr > mid) sum += ask(sgt[rt].r,mid+1,r,posl,posr);
return sum;
}
ll ask(int rt, int l, int r, int kth) {
if(l == r) return l;
int mid = (l + r) >> 1;
if(kth <= sgt[sgt[rt].l].val) return ask(sgt[rt].l,l,mid,kth);
else return ask(sgt[rt].r,mid+1,r,kth-sgt[sgt[rt].l].val);
}
void merge(int &x, int y) {
if(!x || !y) x |= y;
else {
sgt[x].val += sgt[y].val;
merge(sgt[x].l,sgt[y].l);
merge(sgt[x].r,sgt[y].r);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; ++ i) {
int x;
cin >> x;
modify(root[1],1,n,i,x);
}
int last = 1;
while(m --) {
int op, x, y, z;
cin >> op;
if(op == 0) {
cin >> x >> y >> z;
root[++last] = split(root[x],1,n,y,z);
} else if(op == 1) {
cin >> x >> y;
merge(root[x],root[y]);
} else if(op == 2){
cin >> x >> y >> z;
modify(root[x],1,n,z,y);
} else if(op == 3) {
cin >> x >> y >> z;
cout << ask(root[x],1,n,y,z) << "\n";
} else {
cin >> x >> y;
if(y > sgt[root[x]].val) cout << "-1\n";
else cout << ask(root[x],1,n,y) << "\n";
}
}
return 0;
}