原题链接:http://www.tyvj.cn/p/1728
Treap的一些基本操作都在里面了,具体如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define _size(T) (((T)==NULL) ? 0 : ((T)->size))
#define node_size(T) (_size((T)->left) + _size((T)->right) + ((T)->cnt))
typedef struct treap_t{
int key, fix, size, cnt;
struct treap_t *left, *right;
}treap, *Treap;
treap _treap[200000];
int sz = 0;
int random(){
static int x = 1364684679;
x += (x << 2) + 1;
return x;
}
void rotate_right(Treap *T){
Treap k = (*T)->left;
(*T)->left = k->right;
k->right = *T;
(*T)->size = node_size(*T);
k->size = node_size(k);
*T = k;
}
void rotate_left(Treap *T){
Treap k = (*T)->right;
(*T)->right = k->left;
k->left = *T;
(*T)->size = node_size(*T);
k->size = node_size(k);
*T = k;
}
void treap_insert(Treap *T, int key, int fix){
if (*T == NULL){
*T = &_treap[sz++];
memset(*T, 0, sizeof(treap));
(*T)->size = 1, (*T)->cnt = 1, (*T)->key = key, (*T)->fix = fix;
} else if (key < (*T)->key){
(*T)->size++;
treap_insert(&((*T)->left), key, fix);
if ((*T)->left->fix < (*T)->fix)
rotate_right(T);
} else if (key >(*T)->key){
(*T)->size++;
treap_insert(&((*T)->right), key, fix);
if ((*T)->right->fix < (*T)->fix)
rotate_left(T);
} else {
(*T)->cnt++;
(*T)->size++;
}
}
void treap_remove(Treap *T, int key){
if ((*T)->key == key){
if ((*T)->cnt > 1) {
(*T)->cnt--, (*T)->size--;
} else if ((*T)->left == NULL || (*T)->right == NULL){
*T = ((*T)->left != NULL ? (*T)->left : (*T)->right);
} else if ((*T)->left->fix < (*T)->right->fix){
rotate_right(T);
(*T)->size--;
treap_remove(&((*T)->right), key);
} else if ((*T)->left->fix >(*T)->right->fix){
rotate_left(T);
(*T)->size--;
treap_remove(&((*T)->left), key);
}
} else if (key < (*T)->key){
(*T)->size--;
treap_remove(&((*T)->left), key);
} else if (key >(*T)->key){
(*T)->size--;
treap_remove(&((*T)->right), key);
}
}
Treap treap_find_kth(Treap T, int k){
int x = _size(T->left);
if (k < x + 1)
return treap_find_kth(T->left, k);
else if (k > x + T->cnt)
return treap_find_kth(T->right, k - (x + T->cnt));
else return T;
}
int treap_rank(Treap T, int key, int cur)
{
int x = _size(T->left);
if (key == T->key) return x + cur + 1;
else if (key < T->key) return treap_rank(T->left, key, cur);
else return treap_rank(T->right, key, cur + x + T->cnt);
}
int treap_succ(Treap T,int key){
int ret = 0;
while (T != NULL){
if (T->key > key){
ret = T->key;
T = T->left;
}
else T = T->right;
}
return ret;
}
int treap_pred(Treap T, int key){
int ret = 0;
while (T != NULL){
if (T->key < key){
ret = T->key;
T = T->right;
}
else T = T->left;
}
return ret;
}
int main(){
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w+", stdout);
#endif
int i, t, val;
sz = 0;
Treap root = NULL;
scanf("%d", &t);
while (t--){
scanf("%d %d", &i, &val);
switch (i){
case 1:
treap_insert(&root, val, random()); break;
case 2:
treap_remove(&root, val); break;
case 3:
printf("%d\n", treap_rank(root, val, 0)); break;
case 4:
printf("%d\n", treap_find_kth(root, val)->key); break;
case 5:
printf("%d\n", treap_pred(root, val)); break;
case 6:
printf("%d\n", treap_succ(root, val)); break;
}
}
return 0;
}