我只在split里写了可持久化,merge没改,也过了100pts,
void split(int cur, int v, int &x, int &y) {
if(cur == 0) {
x = y = 0;
return;
}
if(val[cur] <= v) {
x = addNode(val[cur]);
pri[x] = pri[cur];
chd[x][0] = chd[cur][0];
split(chd[cur][1], v, chd[x][1], y);
push_up(x);
} else {
y = addNode(val[cur]);
pri[y] = pri[cur];
chd[y][1] = chd[cur][1];
split(chd[cur][0], v, x, chd[y][0]);
push_up(y);
}
}
int merge(int x, int y) {
if(x == 0 || y == 0) return x | y;
if(pri[x] > pri[y]) {
chd[x][1] = merge(chd[x][1], y);
push_up(x);
return x;
} else {
chd[y][0] = merge(x, chd[y][0]);
push_up(y);
return y;
}
}
完整代码
#include<iostream>
#include<random>
#include<ctime>
#define int long long
using namespace std;
const int N = 5E5 + 10;
const int INF = (int)0x3f3f3f3f3f3f3f3f;
int T;
mt19937 rng(time(NULL));
int val[50 * N], pri[50 * N], chd[50 * N][2], sz[50 * N], nn;
int root[N], vcnt;
void push_up(int p) {
sz[p] = sz[chd[p][0]] + sz[chd[p][1]] + 1;
}
int addNode(int v) {
val[++nn] = v;
pri[nn] = rng();
push_up(nn);
return nn;
}
void split(int cur, int v, int &x, int &y) {
if(cur == 0) {
x = y = 0;
return;
}
if(val[cur] <= v) {
x = addNode(val[cur]);
pri[x] = pri[cur];
chd[x][0] = chd[cur][0];
split(chd[cur][1], v, chd[x][1], y);
push_up(x);
} else {
y = addNode(val[cur]);
pri[y] = pri[cur];
chd[y][1] = chd[cur][1];
split(chd[cur][0], v, x, chd[y][0]);
push_up(y);
}
}
int merge(int x, int y) {
if(x == 0 || y == 0) return x | y;
if(pri[x] > pri[y]) {
chd[x][1] = merge(chd[x][1], y);
push_up(x);
return x;
} else {
chd[y][0] = merge(x, chd[y][0]);
push_up(y);
return y;
}
}
void insert(int v, int rt) {
int x, y;
split(root[rt], v, x, y);
root[++vcnt] = merge(merge(x, addNode(v)), y);
}
void del(int v, int rt) {
int x, y, z, w;
split(root[rt], v - 1, x, w);
split(w, v, y, z);
root[++vcnt] = merge(merge(merge(x, chd[y][0]), chd[y][1]), z);
}
int queryRank(int v, int rt) {
int cur = root[rt], res = 0;
while(cur) {
if(val[cur] >= v) {
cur = chd[cur][0];
} else {
res += sz[chd[cur][0]] + 1;
cur = chd[cur][1];
}
}
return res;
}
int queryKth(int k, int rt) {
int cur = root[rt], ans;
while(cur) {
ans = cur;
if(k <= sz[chd[cur][0]]) {
cur = chd[cur][0];
} else if(k == sz[chd[cur][0]] + 1) return val[cur];
else {
k -= sz[chd[cur][0]] + 1;
cur = chd[cur][1];
}
}
return ans;
}
int pre(int v, int rt) {
int cur = root[rt], res = -INF;
while(cur) {
if(val[cur] >= v) {
cur = chd[cur][0];
} else {
res = max(res, val[cur]);
cur = chd[cur][1];
}
}
return res;
}
int suc(int v, int rt) {
int cur = root[rt], res = INF;
while(cur) {
if(val[cur] <= v) {
cur = chd[cur][1];
} else {
res = min(res, val[cur]);
cur = chd[cur][0];
}
}
return res;
}
signed main() {
cin >> T;
while(T--) {
int op, v, x;
cin >> v >> op >> x;
if(op == 1) {
insert(x, v);
} else if(op == 2) {
del(x, v);
} else if(op == 3) {
cout << queryRank(x, v) + 1 << '\n';
root[++vcnt] = root[v];
} else if(op == 4) {
cout << queryKth(x, v) << '\n';
root[++vcnt] = root[v];
} else if(op == 5) {
cout << pre(x, v) << '\n';
root[++vcnt] = root[v];
} else {
cout << suc(x, v) << '\n';
root[++vcnt] = root[v];
}
}
return 0;
}