「Splay」指針版與數組版模板
阿新 • • 發佈:2018-07-25
span clu 子節點 簡單 print div 自己 truct return
splay總是多打打就熟了,先把板子貼在這裏方便查看
Splay的思想還是很簡單的,反正就是把每次查詢到的都splay到根,維護動態平衡
插入的時候就找到位置,splay到根
刪除是最麻煩的,先查找到它並splay到根。然後找到前驅splay到根的左子節點作為根,廢掉原先的根節點,然後把右子節點接到前驅的右子樹上。
排名只要splay到根輸出左子樹+1就好了
kth也不難,從根開始,如果不夠就往左走,要麽是自己,再不行就往右邊走。不要忘了k要減掉左子樹和cnt
前驅後繼只要先插入查一下再刪掉就好了
數組版
/*By QiXingzhi*/ #include <cstdio> #definer read() #define Max(a,b) (((a)>(b)) ? (a) : (b)) #define Min(a,b) (((a)<(b)) ? (a) : (b)) using namespace std; typedef long long ll; const int MAXN = 100010; const int INF = 1061109567; inline int read(){ int x = 0; int w = 1; register int c = getchar(); while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar(); if(c == ‘-‘) w = -1, c = getchar(); while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) +(x << 1) + c - ‘0‘, c = getchar(); return x * w; } struct Splay{ int ch[MAXN][2], fa[MAXN], val[MAXN], size[MAXN], cnt[MAXN], root, num_node; inlinebool Son(int f, int x){ return ch[f][1] == x; } inline void Update(int x){ size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x]; } inline void Rotate(int x){ int f = fa[x], gf = fa[f]; int p = Son(f, x), q = !p; ch[f][p] = ch[x][q], fa[ch[x][q]] = f; ch[x][q] = f, fa[f] = x; fa[x] = gf; if(gf != 0) ch[gf][Son(gf,f)] = x; else root = x; Update(x), Update(f); } inline void splay(int x, int target){ while(fa[x] != target){ int f = fa[x], gf = fa[f]; if(gf == target) Rotate(x); else{ if(Son(gf, f) == Son(f, x)) Rotate(f), Rotate(x); else Rotate(x), Rotate(x); } } } inline void Insert(int v){ if(root == 0){ root = ++num_node; size[num_node] = cnt[num_node] = 1; val[num_node] = v; return; } int p = 0; for(int x = root; x != 0; x = ch[x][p]){ p = v > val[x]; if(v == val[x]){ ++cnt[x], splay(x, 0); return; } if(ch[x][p] == 0){ ch[x][p] = ++num_node; fa[ch[x][p]] = x; size[ch[x][p]] = cnt[ch[x][p]] = 1; val[ch[x][p]] = v; splay(ch[x][p], 0); return; } } } inline void Find(int v){ int x = root, p; for(; x != 0; x = ch[x][p]){ if(v == val[x]){ splay(x, 0); return; } p = v > val[x]; if(ch[x][p] == 0){ splay(x, 0); return; } } } inline void Delete(int v){ Find(v); if(val[root] != v) return; if(cnt[root] > 1){ --cnt[root]; return; } if(ch[root][0] == 0 && ch[root][1] == 0){ root = fa[root] = 0; return; } if(ch[root][0] == 0){ root = ch[root][1], fa[root] = 0; return; } if(ch[root][1] == 0){ root = ch[root][0], fa[root] = 0; return; } int l_max = ch[root][0]; for(; ; l_max = ch[l_max][1]) if(ch[l_max][1] == 0) break; splay(l_max, root); int pre_root = root; root = l_max; fa[root] = 0; ch[root][1] = ch[pre_root][1]; if(ch[pre_root][1] != 0) fa[ch[pre_root][1]] = root; } inline int Pre(int v){ Insert(v); int x = ch[root][0], ans; for(;; x = ch[x][1]) if(ch[x][1] == 0){ ans = val[x]; break; } Delete(v); return ans; } inline int Nxt(int v){ Insert(v); int x = ch[root][1], ans; for(; ; x = ch[x][0]) if(ch[x][0] == 0){ ans = val[x]; break; } Delete(v); return ans; } inline int Kth(int k){ int x = root, p = 0; for(;;){ if(size[ch[x][0]] + cnt[x] >= k && size[ch[x][0]] < k) return val[x]; else if(size[ch[x][0]] >= k) x = ch[x][0]; else{ k -= (size[ch[x][0]] + cnt[x]); x = ch[x][1]; } } } inline int Rank(int v){ Find(v); return (size[ch[root][0]] + 1); } }qxz; int n,opt,x; int main(){ n = r; while(n--){ opt = r, x = r; if(opt == 1) qxz.Insert(x); if(opt == 2) qxz.Delete(x); if(opt == 3) printf("%d\n", qxz.Rank(x)); if(opt == 4) printf("%d\n", qxz.Kth(x)); if(opt == 5) printf("%d\n", qxz.Pre(x)); if(opt == 6) printf("%d\n", qxz.Nxt(x)); } return 0; }
指針版
/*This Program is written by QiXingZhi*/ #include <cstdio> #define N (100010) #define ll long long #define INF (0x7f7f7f7f) #define read(x) x=Rd() #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (((a) < (b)) ? (a) : (b)) #define FILE_IN(x) freopen(x".in","r",stdin) using namespace std; inline int Rd(){ char c = getchar(); int x = 0;int w = 1; while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c=getchar(); if(c == ‘-‘) w = -1, c = getchar(); while(c >= ‘0‘ && c <= ‘9‘) x = (x<<3)+(x<<1)+c-48,c = getchar(); return x * w; } struct Node{ int val,sz,cnt; Node* fa; Node* s[2]; Node(){fa=s[0]=s[1]=NULL; val=sz=cnt=0; } }; int n,m,opt,x; Node* tree; inline bool Rson(Node* a, Node* b){return ((a->s[1])==(b));} inline int Size(Node* o){ if(o == NULL) return 0; return o->sz; } inline void Update(Node* o){ if(o == NULL) return; o->sz = o->cnt + Size(o->s[0]) + Size(o->s[1]); } inline void Rotate(Node* x){ Node *f = x->fa, *gf = f->fa; bool p = Rson(f,x),q = !p; f->s[p] = x->s[q]; if(x->s[q] != NULL) x->s[q]->fa = f; x->s[q] = f,f->fa = x,x->fa = gf; if(gf != NULL) gf->s[Rson(gf,f)] = x; else tree = x; Update(x),Update(f); } inline void Splay(Node* x, Node* t){ while(x->fa != t){ Node *f = x->fa, *gf = f->fa; if(gf == t)Rotate(x); else{ bool p = Rson(f,x); if(Rson(gf,f) ^ Rson(f,x)) Rotate(x),Rotate(x); else Rotate(f),Rotate(x); } } } inline void Insert(int x){ bool b; if(tree == NULL){ tree = new Node(); tree->val = x, tree->cnt = tree->sz = 1; return; } for(Node* o = tree; o != NULL; ){ b = x >= o->val; if(o->val == x){ ++o->cnt; Splay(o,NULL); return; }else{ if(o->s[b] == NULL){ o->s[b] = new Node(); o->s[b]->fa = o; o->s[b]->val = x; o->s[b]->cnt = o->s[b]->sz = 1; // Update(o); Splay(o->s[b],NULL); return; } } o = o->s[b]; } } inline void Find(int val){ Node *o = tree; for(; o != NULL; o = o->s[val >= o->val]) if(o->val == val) break; if(o != NULL) Splay(o,NULL); } inline int Rnk(int x){ Find(x); return Size(tree->s[0]) + 1; } inline int Kth(int k){ Node* o = tree; for(;;){ if(Size(o->s[0])+o->cnt >= k && Size(o->s[0]) < k) return o->val; else if(Size(o->s[0]) >= k) o = o->s[0]; else{ k -= (Size(o->s[0]) + o->cnt); o = o->s[1]; } } } inline void Delete(int val){ Find(val); if(tree->val != val) return; if(tree->cnt > 1){ --tree->cnt; return; } else if(tree->s[0] == NULL){ tree = tree->s[1]; if(tree != NULL) tree->fa = NULL; } else if(tree->s[1] == NULL){ tree = tree->s[0]; if(tree != NULL) tree->fa = NULL; } else{ Node* l_max = tree->s[0]; for(; l_max->s[1] != NULL; l_max = l_max->s[1]); Splay(l_max,tree); Node* pre_tree = tree; tree = l_max; tree->fa = NULL; tree->s[1] = pre_tree->s[1]; if(pre_tree->s[1] != NULL) pre_tree->s[1]->fa = tree; } } inline int Pre(int val){ Insert(val); Node* o = tree->s[0]; for(; o->s[1] != NULL; o = o->s[1]); Delete(val); return o->val; } inline int Nxt(int val){ Insert(val); Node* o = tree->s[1]; for(; o->s[0] != NULL; o = o->s[0]); Delete(val); return o->val; } int main(){ read(n); while(n--){ read(opt),read(x); if(opt == 1) Insert(x); if(opt == 2) Delete(x); if(opt == 3) printf("%d\n", Rnk(x)); if(opt == 4) printf("%d\n", Kth(x)); if(opt == 5) printf("%d\n", Pre(x)); if(opt == 6) printf("%d\n", Nxt(x)); } return 0; }
「Splay」指針版與數組版模板