函数意义
可持久化Treap本质上市一个二叉平衡树,若不对其规则进行修改,中序遍历后得出的序列是递增的。
void maintain(o)
: 计算结点o的size
int lowCount(key)
: 比key所在位置小1
int upperCount(key)
: key所在的位置,如果有多个相同的key,选位置最大的
int select(int k)
: 找出第k小的数的值
Node* merge(Node* a, Node* b):
合并,要用rank来合并
void split(Node*a, int k, Node*& l, Node*& r)
: 拆分,k包含在l中
int rank(int key):
key的排名
void insert(int key):
插入key
int pred(int key)
: 找前驱,比key小的数中最大的那个
int succ(int key):
找后继,比key大的数中最小的那个
数组版(洛谷平衡树模板题)
#include <iostream>
using namespace std;
const int maxn = 1e6+5;
#define lc son[o][0]
#define rc son[o][1]
struct Treap {
int son[maxn][2], val[maxn], r[maxn], sz[maxn];
bool flag[maxn];
int root,tot;
int node(int x) {
val[tot] = x;
sz[tot] = 1;
son[tot][0] = son[tot][1] = 0;
flag[tot] = false;
r[tot] = rand();
return tot++;
}
void init() {
root = 0; tot = 1;
son[0][0] = son[1][0] = sz[0] = r[0] = 0;
}
void maintain(int o) {
sz[o] = 1;
sz[o] += (sz[lc]+sz[rc]);
}
void split(int o, int k, int &l, int &r) {
if(o == 0) {
l = r = 0;
}
else if(sz[lc] >= k) {
r = o;
split(lc, k, l, lc);
maintain(o);
}
else {
l = o;
split(rc, k-sz[lc]-1, rc, r);
maintain(o);
}
}
int merge(int a,int b) {
if(a == 0 || b == 0) {
return a+b;
}
if(r[a] < r[b]) { // 必须按rank
son[a][1] = merge(son[a][1], b);
maintain(a);
return a;
}
else {
son[b][0] = merge(a, son[b][0]);
maintain(b);
return b;
}
}
int lowCount(int o,int x){
if(o == 0)
return 0;
return val[o] >= x ? lowCount(lc, x) : lowCount(rc, x)+sz[lc]+1;
}
int upCount(int o, int x) {
if(o == 0)
return 0;
return val[o] > x ? upCount(lc, x) : upCount(rc, x)+sz[lc]+1;
}
int rank(int x) {
return lowCount(root, x)+1;
}
int kth(int k) {
return select(root, k);
}
int select(int o, int k) {
while(sz[lc]+1 != k) {
if(sz[lc] >= k) {
o = lc;
}
else {
k -= (sz[lc]+1);
o = rc;
}
}
return val[o];
}
void insert(int x) {
int pos = lowCount(root, x);
int a,b;
split(root, pos, a, b);
int t = node(x);
root = merge(merge(a, t), b);
}
void del(int val){
int pos = lowCount(root, val);
int a,b,x,y;
split(root, pos, a, b);
split(b, 1, x, y);
root = merge(a, y);
}
int pred(int x) {
return kth(lowCount(root, x));
}
int succ(int x) {
return kth(upCount(root, x)+1);
}
void show() {
print(root);
}
void print(int o) {
if(lc != 0)
print(lc);
cout << val[o] << endl;
if(rc != 0)
print(rc);
}
};
Treap treap;
typedef long long ll;
inline int readInt() {
int n = 0, ch = getchar();
bool flag = false;
while (!isdigit(ch)) flag |= ch == '-', ch = getchar();
while (isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
return flag ? -n : n;
}
int main() {
int n;
treap.init();
scanf("%d", &n);
while(n--) {
int opt,val;
opt = readInt();
val = readInt();
if(opt == 1) {
treap.insert(val);
}
if(opt == 2) {
treap.del(val);
}
if(opt == 3) {
cout << treap.rank(val) << endl;
}
if(opt == 4) {
cout << treap.kth(val) << endl;
}
if(opt == 5) {
// treap.show();
cout << treap.pred(val) << endl;
}
if(opt == 6) {
cout << treap.succ(val) << endl;
}
}
// treap.show();
return 0;
}
指针版(Uva11922)
#include <iostream>
using namespace std;
const int maxn = 1e6+5;
#define lc son[o][0]
#define rc son[o][1]
struct Treap {
int son[maxn][2], val[maxn], r[maxn], sz[maxn];
bool flag[maxn];
int root,tot;
int node(int x) {
val[tot] = x;
sz[tot] = 1;
son[tot][0] = son[tot][1] = 0;
flag[tot] = false;
r[tot] = rand();
return tot++;
}
void init() {
root = 0; tot = 1;
son[0][0] = son[1][0] = sz[0] = r[0] = 0;
}
void maintain(int o) {
sz[o] = 1;
sz[o] += (sz[lc]+sz[rc]);
}
void split(int o, int k, int &l, int &r) {
if(o == 0) {
l = r = 0;
}
else if(sz[lc] >= k) {
r = o;
split(lc, k, l, lc);
maintain(o);
}
else {
l = o;
split(rc, k-sz[lc]-1, rc, r);
maintain(o);
}
}
int merge(int a,int b) {
if(a == 0 || b == 0) {
return a+b;
}
if(r[a] < r[b]) { // 必须按rank
son[a][1] = merge(son[a][1], b);
maintain(a);
return a;
}
else {
son[b][0] = merge(a, son[b][0]);
maintain(b);
return b;
}
}
int lowCount(int o,int x){
if(o == 0)
return 0;
return val[o] >= x ? lowCount(lc, x) : lowCount(rc, x)+sz[lc]+1;
}
int upCount(int o, int x) {
if(o == 0)
return 0;
return val[o] > x ? upCount(lc, x) : upCount(rc, x)+sz[lc]+1;
}
int rank(int x) {
return lowCount(root, x)+1;
}
int kth(int k) {
return select(root, k);
}
int select(int o, int k) {
while(sz[lc]+1 != k) {
if(sz[lc] >= k) {
o = lc;
}
else {
k -= (sz[lc]+1);
o = rc;
}
}
return val[o];
}
void insert(int x) {
int pos = lowCount(root, x);
int a,b;
split(root, pos, a, b);
int t = node(x);
root = merge(merge(a, t), b);
}
void del(int val){
int pos = lowCount(root, val);
int a,b,x,y;
split(root, pos, a, b);
split(b, 1, x, y);
root = merge(a, y);
}
int pred(int x) {
return kth(lowCount(root, x));
}
int succ(int x) {
return kth(upCount(root, x)+1);
}
void show() {
print(root);
}
void print(int o) {
if(lc != 0)
print(lc);
cout << val[o] << endl;
if(rc != 0)
print(rc);
}
};
Treap treap;
typedef long long ll;
inline int readInt() {
int n = 0, ch = getchar();
bool flag = false;
while (!isdigit(ch)) flag |= ch == '-', ch = getchar();
while (isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
return flag ? -n : n;
}
int main() {
int n;
treap.init();
scanf("%d", &n);
while(n--) {
int opt,val;
opt = readInt();
val = readInt();
if(opt == 1) {
treap.insert(val);
}
if(opt == 2) {
treap.del(val);
}
if(opt == 3) {
cout << treap.rank(val) << endl;
}
if(opt == 4) {
cout << treap.kth(val) << endl;
}
if(opt == 5) {
// treap.show();
cout << treap.pred(val) << endl;
}
if(opt == 6) {
cout << treap.succ(val) << endl;
}
}
// treap.show();
return 0;
}