7.Bzoj3224: Tyvj 1728 普通平衡樹(Treap)
阿新 • • 發佈:2018-11-29
Bzoj3224: Tyvj 1728 普通平衡樹(Treap)
終於自己敲出來了Treap。。。。。。拿來當板子還是挺好用的.
操作1,顯然根據二叉搜尋樹的性質直接建就好了.
操作2,如果有兩個兒子,則把這個點下旋下去,直到只有一個兒子或者沒有.
操作3,查詢比他小的數,記錄一個size,表示這個點有多少個兒子.
操作4,排名為x , 那麼就有x - 1個數小於等於這個數.
操作5,直接去min再根據二叉搜尋樹的性質,就ok了.
操作6,同操作5.
#include <iostream> #include <cstdio> #include <algorithm> #define rep(i , x, p) for(int i = x;i <= p;++ i) #define sep(i , x, p) for(int i = x;i >= p;-- i) #define gc getchar() #define pc putchar using namespace std; const int inf = 1e9; const int maxN = 100000 + 7; inline int read() {int x = 0,f = 1;char c = gc;while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;} void print(int x) {if(x < 0) pc('-') , x = -x;if(x >= 10) print(x / 10);pc(x % 10 + '0');} int ch[maxN][2] , pos[maxN], size[maxN], key[maxN], rt, cnt; void up(int i) {size[i] = size[ch[i][0]] + size[ch[i][1]] + 1;return ;} void spin(int &i , int p) { int tmp = ch[i][p]; ch[i][p] = ch[tmp][!p];ch[tmp][!p] = i;up(i);i = tmp;up(i); } void Insert(int &i , int x) { if(!i) { ++ cnt;i = cnt; size[i] = 1;pos[i] = rand(); key[i] = x; return ; } if(key[i] >= x) { Insert(ch[i][0] , x); if(pos[i] < pos[ch[i][0]]) spin(i , 0); } else { Insert(ch[i][1] , x); if(pos[i] < pos[ch[i][1]]) spin(i , 1); } up(i); } int getrank(int &i , int x) { if(!i) return 1; if(key[i] >= x) return getrank(ch[i][0] , x); return getrank(ch[i][1] , x) + size[ch[i][0]] + 1; } int is_rank(int i , int x) { if(size[ch[i][0]] == x - 1) return key[i]; if(size[ch[i][0]] >= x) return is_rank(ch[i][0] , x); return is_rank(ch[i][1] , x - size[ch[i][0]] - 1); } int pre(int i , int x) { if(!i) return -inf; if(key[i] < x) return max(pre(ch[i][1] , x) , key[i]); return pre(ch[i][0] , x); } int nxt(int i , int x) { if(!i) return inf; if(key[i] > x) return min(nxt(ch[i][0] , x) , key[i]); return nxt(ch[i][1] , x); } void Dele(int &i , int x) { if(key[i] == x) { if(ch[i][0] * ch[i][1] == 0) {i = ch[i][0] + ch[i][1];return ;} if(pos[ch[i][0]] > pos[ch[i][1]]) {spin(i , 1); Dele(ch[i][0] , x);} else {spin(i , 0) , Dele(ch[i][1] , x);} }else { if(x < key[i]) Dele(ch[i][0] , x); else Dele(ch[i][1] , x); } up(i); } int main() { int n = read() , opt , x; rep(i , 1, n) { opt = read();x = read(); if(opt == 1) Insert(rt , x); else if(opt == 2) Dele(rt , x); else if(opt == 3) print(getrank(rt , x)) , pc('\n'); else if(opt == 4) print(is_rank(rt , x)) , pc('\n'); else if(opt == 5) print(pre(rt , x)) , pc('\n'); else print(nxt(rt , x)) , pc('\n'); } return 0; }
考察點
Treap的基本操作