//无旋treap真滴nb。。基于spilt和merge两个函数可以做很多事情。。
之前有一道模板题基于那道题多了版本更新操作,思路和主席树的思路类似,只新建插入或删除的那条链上的点,其他的点参照之前的版本。
然后就没有然后了。。
1.因为要复制一些节点的信息,把节点的数据用结构体存起来比较好写。
2.空间开40倍。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int n, m;
struct Treap{
struct node{
int ch[2], dat;
int val, size;
}tr[maxn*40];
int root[maxn];
int tot, cnt;
void pushup(int rt) {
tr[rt].size = tr[tr[rt].ch[0]].size + 1 + tr[tr[rt].ch[1]].size;
}
int copy(int rt) {
tot++;
tr[tot] = tr[rt];
return tot;
}
int newnode(int x) {
tot++;
tr[tot].size = 1;
tr[tot].dat = rand();
tr[tot].val = x;
return tot;
}
void spilt(int rt, int k, int &x, int &y) {
if(!rt) x = y = 0;
else{
if(tr[tr[rt].ch[0]].size >= k) {
y = copy(rt);
spilt(tr[y].ch[0], k, x, tr[y].ch[0]);
pushup(y);
}
else{
x = copy(rt);
spilt(tr[x].ch[1], k-tr[tr[x].ch[0]].size-1, tr[x].ch[1], y);
pushup(x);
}
}
}
int merge(int A, int B) {
if(!A || !B) return A + B;
if(tr[A].dat < tr[B].dat) {
int res = copy(A);
tr[res].ch[1] = merge(tr[res].ch[1], B);
pushup(res);
return res;
}
else {
int res = copy(B);
tr[res].ch[0] = merge(A, tr[res].ch[0]);
pushup(res);
return res;
}
}
int insert(int rt, int k, int x) {
int node = newnode(x);
int a, b;
spilt(rt, k-1, a, b);
// puts("!!!");
// dfs(a);puts("");
// dfs(b);puts("");
// puts("!!!");
return merge(merge(a, node), b);
}
int del(int rt, int k) {
int a, b, c;
spilt(rt, k-1, a, b);
spilt(b, 1, b, c);
return merge(a, c);
}
int query(int rt, int k) {
if(!rt) return -1;
if(k <= tr[tr[rt].ch[0]].size) return query(tr[rt].ch[0], k);
else if(k == tr[tr[rt].ch[0]].size + 1) return tr[rt].val;
else return query(tr[rt].ch[1], k-1-tr[tr[rt].ch[0]].size);
}
void dfs(int rt) {
if(!rt) return;
dfs(tr[rt].ch[0]);
printf("%d ", tr[rt].val);
dfs(tr[rt].ch[1]);
}
void add() {
cnt++;
}
}treap;
void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int op;scanf("%d", &op);
if(op == 1) {
int t, k, val;
scanf("%d%d%d", &t, &k, &val);
treap.add();
treap.root[treap.cnt] = treap.insert(treap.root[t], k, val);
//treap.dfs(treap.root[treap.cnt]);
}
else if(op == 2) {
int k, t;scanf("%d%d", &t, &k);
treap.add();
treap.root[treap.cnt] = treap.del(treap.root[t], k);
//
}
else if(op == 3) {
int t, k;scanf("%d%d", &t, &k);
printf("%d\n", treap.query(treap.root[t], k));
//puts("");
}
//printf("%d\n", treap.size[treap.root[3]]);
//treap.dfs(treap.root[treap.cnt]);
//puts("");
}
return;
}
int main() {
//g++ -std=c++11 -o2 1.cpp -o f && ./f < in.txt
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
while(Case--) {
solve();
}
return 0;
}