1. 程式人生 > >「Splay」指針版與數組版模板

「Splay」指針版與數組版模板

span clu 子節點 簡單 print div 自己 truct return

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\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」指針版與數組版模板