【LG3835】可持久化平衡树
题面
解法一
rope大法好
(rope)基本操作:
#include<ext/rope>
using namespace __gnu_cxx;//rope的命名空间
rope<type> R;
R.push_back(a) //往后插入
R.insert(pos,a)//在pos位置插入a,pos是一个迭代器。
R.erase(pos,n)//在pos位置删除n个元素。
R.replace(pos,x)//从pos开始替换成x
R.substr(pos,x)//从pos开始提取x个。
//多数时候定义rope用指针(方便可持久化) 所以上面的点多数时候要换成->
再配合二分即可实现各种操作
如何进行复制:
rope<type>* R[1000];
R[i] = new rope<type>(*R[v]);
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <ext/rope>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_cxx;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar();
if (ch == '-') w = -1 , ch = getchar();
while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
return w * data;
}
#define MAX_N 500005
rope<int> *rop[MAX_N];
int N;
int main () {
N = gi();
rop[0] = new rope<int>();
for (int i = 1; i <= N; i++) {
int v = gi(), opt = gi(), x = gi();
rop[i] = new rope<int>(*rop[v]);
if (opt == 1) rop[i]->insert(lower_bound(rop[i]->begin(), rop[i]->end(), x) - rop[i]->begin(), x);
if (opt == 2) {
auto ite = lower_bound(rop[i]->begin(), rop[i]->end(), x);
if (ite != rop[i]->end() && *ite == x) rop[i]->erase(ite - rop[i]->begin(), 1);
}
if (opt == 3)
printf("%d
", (int)(lower_bound(rop[i]->begin(), rop[i]->end(), x) - rop[i]->begin()) + 1);
if (opt == 4) printf("%d
", *(rop[i]->begin() + x - 1));
if (opt == 5) {
auto ite = lower_bound(rop[i]->begin(), rop[i]->end(), x);
if (ite == rop[i]->begin() - 1) puts("-2147483647");
else --ite, printf("%d
", *ite);
}
if (opt == 6) {
auto ite = upper_bound(rop[i]->begin(), rop[i]->end(), x);
if (ite == rop[i]->end()) puts("2147483647");
printf("%d
", *ite);
}
}
return 0;
}
解法二
用可持久化(trie)可以很方便地实现
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 5e5 + 5;
const int T = 1e9;
struct Trie { int ch[2], size; } t[MAX_N << 5];
int N, rt[MAX_N], tot;
bool find(int o, int v) {
v += T;
for (int i = 31; ~i; i--) {
int c = v >> i & 1;
if (!t[o].size || !o) return 0;
o = t[o].ch[c];
}
return 1;
}
void insert(int &x, int p, int v) {
x = ++tot; int o = x;
v += T, t[o].size = t[p].size + 1;
for (int i = 31; ~i; i--) {
int c = v >> i & 1;
t[o].ch[c ^ 1] = t[p].ch[c ^ 1];
t[o].ch[c] = ++tot;
o = t[o].ch[c], p = t[p].ch[c];
t[o].size = t[p].size + 1;
}
}
void erase(int &x, int p, int v) {
if (!find(p, v)) return (void)(x = p);
x = ++tot; int o = x;
v += T, t[o].size = t[p].size - 1;
for (int i = 31; ~i; i--) {
int c = v >> i & 1;
t[o].ch[c ^ 1] = t[p].ch[c ^ 1];
t[o].ch[c] = ++tot;
o = t[o].ch[c], p = t[p].ch[c];
t[o].size = t[p].size - 1;
}
}
int Kth(int o, int k) {
long long res = -T;
for (int i = 31; ~i; i--) {
int sz = t[t[o].ch[0]].size;
if (k <= sz) o = t[o].ch[0];
else res += (1 << i), o = t[o].ch[1], k -= sz;
}
return res;
}
int LR(int o, int v) {
v += T; int res = 0;
for (int i = 31; ~i; i--) {
int c = v >> i & 1;
if (c) res += t[t[o].ch[0]].size;
o = t[o].ch[c];
if (!o || !t[o].size) return res;
}
return res;
}
int UR(int o, int v) {
v += T; int res = 0;
for (int i = 31; ~i; i--) {
int c = v >> i & 1;
if (!c) res += t[t[o].ch[1]].size;
o = t[o].ch[c];
if (!o || !t[o].size) return res;
}
return res;
}
int Rnk(int o, int v) { return LR(o, v) + 1; }
signed main () {
N = gi();
rt[0] = ++tot;
for (int i = 1; i <= N; i++) {
int v = gi(), op = gi(), x = gi();
if (op == 1) insert(rt[i], rt[v], x);
if (op == 2) erase(rt[i], rt[v], x);
if (op == 3) rt[i] = rt[v], printf("%d
", Rnk(rt[i], x));
if (op == 4) rt[i] = rt[v], printf("%d
", Kth(rt[i], x));
if (op == 5) {
rt[i] = rt[v];
int res = LR(rt[i], x);
if (!res) printf("%d
", -INT_MAX);
else printf("%d
", Kth(rt[i], res));
}
if (op == 6) {
rt[i] = rt[v];
int res = UR(rt[i], x);
if (!res) printf("%d
", INT_MAX);
else printf("%d
", Kth(rt[i], t[rt[i]].size - res + 1));
}
}
return 0;
}