模板Splay

Posted benjamin-cpp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板Splay相关的知识,希望对你有一定的参考价值。

Splay应该是我目前写过的最长的代码了(188)

#include <iostream>
#include <cstdio>
using namespace std;
//Mystery_Sky
//Splay
#define M 1000100
#define INF 0x3f3f3f3f
#define ll long long
inline int read()

    int x=0,f=1; char c=getchar();
    while(c<'0'||c>'9') if(c=='-')f=-1;c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0';c=getchar();
    return x*f;


int fa[M], val[M], cnt[M], son[M][2], size[M];
int tot, root, n;

inline void S_clear(int p)

    son[p][0] = son[p][1] = fa[p] = size[p] = cnt[p] = val[p] = 0;


inline void update(int p)

    if (p)  
        size[p] = cnt[p];  
        if (son[p][0]) size[p] += size[son[p][0]];  
        if (son[p][1]) size[p] += size[son[p][1]];  
      
    return ;


inline bool get_which(int p)

    return son[fa[p]][1] == p;


inline void Rotate(int p)

    int father = fa[p], grfa = fa[father], w_son = get_which(p);
    son[father][w_son] = son[p][w_son^1];
    fa[son[father][w_son]] = father;
    son[p][w_son^1] = father;
    fa[father] = p;
    fa[p] = grfa;
    if(grfa) 
        son[grfa][son[grfa][1] == father] = p;
    
    update(father);
    update(p);


inline void Splay(int p)//关键操作。 

    for(int f; f = fa[p]; Rotate(p))
        if(fa[f]) Rotate((get_which(p) == get_which(f)) ? f : p);
    root = p;


inline void insert(int x)

    if(!root) 
        tot++;
        son[tot][0] = son[tot][1] = fa[tot] = 0;
        root = tot;
        size[tot] = cnt[tot]++;
        val[tot] = x;
    
    int now = root, f = 0;
    while(1) 
        if(x == val[now]) 
            cnt[now]++;
            update(now);
            update(f);
            Splay(now);
            break;
        
        f = now;
        now = son[now][val[now]<x];
        if(!now) 
            tot++;
            son[tot][0] = son[tot][1] = 0;
            fa[tot] = f;
            size[tot] = cnt[tot] = 1;
            son[f][val[f]<x] = tot;
            val[tot] = x;
            update(f);
            Splay(tot);
            break;
        
    


inline int query_val(int rank)

    int p = root;
    while(1) 
        if(son[p][0] && rank <= size[son[p][0]]) p = son[p][0];
        else 
            int temp = size[son[p][0]] + cnt[p];
            if(rank <= temp) return val[p];
            rank -= temp;
            p = son[p][1];
        
    


inline int query_rank(int x)

    int p = root, ans = 0;
    while(1) 
        if(x < val[p]) p = son[p][0];
        else 
            ans += size[son[p][0]];
            if(x == val[p]) 
                Splay(p);
                return ans + 1;
            
            ans += cnt[p];
            p = son[p][1];
        
    


inline int query_pre()

    int p = son[root][0];
    while(son[p][1]) p = son[p][1];
    return p;


inline int query_next()

    int p = son[root][1];
    while(son[p][0]) p = son[p][0];
    return p;


inline void Delete(int x)

    int rank = query_rank(x);
    if(cnt[root] > 1) 
        cnt[root]--;
        update(root);
        return;
    
    if(!son[root][0] && !son[root][1]) 
        S_clear(root);
        root = 0;
        return;
    
    if(!son[root][0]) 
        int old_root = root;
        root = son[root][1];
        fa[root] = 0;
        S_clear(old_root);
        return;
    
    else if(!son[root][1]) 
        int old_root = root;
        root = son[root][0];
        fa[root] = 0;
        S_clear(old_root);
        return;
    
    int lmax = query_pre(), old_root = root;
    Splay(lmax);
    son[root][1] = son[old_root][1];
    fa[son[old_root][1]] = root;
    S_clear(old_root);
    update(root);


int main() 
    n = read();
    for(int i = 1; i <= n; i++) 
        int opt = read(), x = read();
        if(opt == 1) insert(x);
        else if(opt == 2) Delete(x);
        else if(opt == 3) printf("%d\n", query_rank(x));
        else if(opt == 4) printf("%d\n", query_val(x));
        else if(opt == 5) insert(x), printf("%d\n", val[query_pre()]), Delete(x);
        else if(opt == 6) insert(x), printf("%d\n", val[query_next()]), Delete(x);
    
    return 0;

以上是关于模板Splay的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3224 普通平衡树 splay模板

Splay(区间翻转) 模板

P3391 模板文艺平衡树(Splay)

Splay模板

模板Splay

「Splay」指针版与数组版模板