「Splay」指针版与数组版模板
Posted qixingzhi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「Splay」指针版与数组版模板相关的知识,希望对你有一定的参考价值。
splay总是多打打就熟了,先把板子贴在这里方便查看
Splay的思想还是很简单的,反正就是把每次查询到的都splay到根,维护动态平衡
插入的时候就找到位置,splay到根
删除是最麻烦的,先查找到它并splay到根。然后找到前驱splay到根的左子节点作为根,废掉原先的根节点,然后把右子节点接到前驱的右子树上。
排名只要splay到根输出左子树+1就好了
kth也不难,从根开始,如果不够就往左走,要么是自己,再不行就往右边走。不要忘了k要减掉左子树和cnt
前驱后继只要先插入查一下再删掉就好了
数组版
/*By QiXingzhi*/ #include <cstdio> #define r 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; inline bool 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 ", qxz.Rank(x)); if(opt == 4) printf("%d ", qxz.Kth(x)); if(opt == 5) printf("%d ", qxz.Pre(x)); if(opt == 6) printf("%d ", 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 ", Rnk(x)); if(opt == 4) printf("%d ", Kth(x)); if(opt == 5) printf("%d ", Pre(x)); if(opt == 6) printf("%d ", Nxt(x)); } return 0; }
以上是关于「Splay」指针版与数组版模板的主要内容,如果未能解决你的问题,请参考以下文章
[模板]洛谷T3369 普通平衡树 链表&递归版无父指针版Splay