Splay 伸展树 bzoj3224 bzoj3223

Splay 伸展树, 平衡树的一种实现方法

splay的精髓在于 rotate函数, 这里不多作介绍, 以及有大牛把原理及实现方法解释的很清楚了,这里只贴一下自己实现的代码,代码参考  :史上最详尽的平衡树(splay)讲解与模板

下面是我自己的代码:

bzoj 3224 

传送门:Tyvj 1728 普通平衡树

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=1e6+100;

int fa[N], ch[N][2], siz[N], cnt[N], key[N];
int sz, root;

inline void update(int x){
    siz[x] = cnt[x];
    siz[x] += siz[ch[x][0]] + siz[ch[x][1]];
}

inline void Clear(int x){
    fa[x] = ch[x][0] = ch[x][1] = siz[x] = cnt[x] = key[x] = 0;
}

inline bool get(int x){
    return ch[fa[x]][1] == x;
}

void Rotate(int x){
    int old = fa[x], oldf = fa[old], which = get(x);
    ch[old][which] = ch[x][which^1], fa[ch[x][which^1]] = old;
    ch[x][which^1] = old, fa[old] = x;
    fa[x] = oldf;
    if(oldf) ch[oldf][ch[oldf][1]==old]=x;
    update(old), update(x);
}

void splay(int x){
    while(fa[x]){
        if(get(x) == get(fa[x]) && fa[fa[x]]) Rotate(fa[x]);
        Rotate(x);//cout<<" x \n";
    }
    root = x;
}

void Insert(int x){
    if(root == 0){
        sz++, root = cnt[sz] = siz[sz] = 1, key[sz] = x;
        return;
    }
    int now = root, f = 0;
    while(1){
        if(key[now] == x){
            cnt[now]++, update(now), update(f), splay(now); break;
        }
        f = now, now = ch[now][x>key[now]];
        if(now == 0){
            sz++, cnt[sz] = 1, key[sz] = x, siz[sz] = 1, fa[sz] = f, ch[f][x>key[f]] = sz;
            update(f), splay(sz); break;
        }
    }
}

inline int finds(int v){
    int now = root, ret=0;
    while(1){
        if(v == key[now]){
            ret += siz[ch[now][0]];
            splay(now);
            return ret+1;
        }
        if(v < key[now]) now = ch[now][0];
        else if(v > key[now]) ret += cnt[now] + siz[ch[now][0]], now = ch[now][1];
    }
}

inline int findx(int x){
    int now = root;
    while(1){
        int t = siz[ch[now][0]] + cnt[now];
        if(x <= siz[ch[now][0]]) now = ch[now][0];
        else if(x <= t) return key[now];
        else x -= t, now = ch[now][1];
    }
}

inline int pre(){
    int now = ch[root][0];
    while(ch[now][1]) now = ch[now][1];
    return now;
}

inline int nex(){
    int now = ch[root][1];//cout<<key[ch[now][1]]<<" u \n";
    while(ch[now][0]) now = ch[now][0];
    return now;
}

inline void del(int x){//cout<<key[root]<<endl;
    finds(x);
    if(cnt[root]>1){
        cnt[root]--, update(root); return;
    }
    if(ch[root][0]==0 && ch[root][1]==0){
        Clear(root), root =0; return;
    }
    if(ch[root][0] && ch[root][1]){
        int p = pre(), old = root;
        splay(p);
        fa[ch[old][1]] = root;
        ch[root][1] = ch[old][1];
        Clear(old), update(root);
        return;
    }
    int old = root;
    root = ch[root][ch[root][0]==0], fa[root] = 0, Clear(old);
}
int main(){
    int n, opt, x;
    scanf("%d", &n);
    for (int i=1; i<=n; ++i){
        scanf("%d %d",&opt, &x);
        switch(opt){
            case 1: Insert(x); break;
            case 2: del(x); break;
            case 3: printf("%d\n",finds(x)); break;
            case 4: printf("%d\n",findx(x)); break;
            case 5: Insert(x); printf("%d\n", key[pre()]); del(x); break;
            case 6: Insert(x); printf("%d\n", key[nex()]); del(x); break;
        }
    }
    return 0;
}

 bzoj 3223

传送门:HYSBZ - 3223 

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=1e5+100;

int siz[N], ch[N][2], cnt[N], key[N], fa[N], lazy[N];
int root, sz, n, m;

void Clear(int x){
    siz[x] = ch[x][0] = ch[x][1] = cnt[x] = key[x] = fa[x] = 0;
}

void update(int x){
    siz[x] = cnt[x];
    siz[x] += siz[ch[x][0]] + siz[ch[x][1]];
}

bool get(int x){
    return ch[fa[x]][1] == x;
}

void pushdown(int x){
    if(lazy[x]){
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]] ^= 1, lazy[ch[x][1]] ^= 1;
    }
    lazy[x] = 0;
}
void Rotate(int x){
    pushdown(fa[x]), pushdown(x);
    int fx = fa[x], ffx = fa[fx], which = get(x);
    ch[fx][which] = ch[x][which^1], fa[ch[x][which^1]] = fx;
    ch[x][which^1] = fx, fa[fx] = x;
    fa[x] = ffx;
    if(ffx) ch[ffx][ch[ffx][1]==fx] = x;
    update(fx), update(x);
}

void splay(int x, int goal){
    while(fa[x] != goal){
        if(get(x)==get(fa[x]) && fa[fa[x]] && fa[fa[x]]!=goal)
            Rotate(fa[x]);
        Rotate(x);
    }
    if(goal==0) root = x;
}

int findx(int x){
    int now = root;
    pushdown(now);
    while(1){
        int t = cnt[now] + siz[ch[now][0]];
        if(x <= siz[ch[now][0]]) now = ch[now][0];
        else if(x <= t) return now;
        else x -= t, now = ch[now][1];
        pushdown(now);
    }
}

void change(int l, int r){
    int fl = findx(l),  fr = findx(r+2); //cout<<key[fl]<<"qq\n";
    splay(fl, 0), splay(fr, root);
    lazy[ch[ch[root][1]][0]] ^= 1;
}

void Insert(int x){
    if(root == 0){
        sz++, root = cnt[sz] = siz[sz] = 1, key[sz] = x;
        return;
    }
    int now = root, f = 0;
    while(1){
        if(key[now] == x){
            cnt[now]++, update(now), update(f), splay(now, 0); break;
        }
        f = now, now = ch[now][x>key[now]];
        if(now == 0){
            sz++, cnt[sz] = 1, key[sz] = x, siz[sz] = 1, fa[sz] = f, ch[f][x>key[f]] = sz;
            update(f), splay(sz, 0); break;
        }
    }
}

int build(int l, int r, int f){//cout<<" UU\n";
    if(l > r) return 0;
    int mid = l+r>>1, u = ++sz;
    if(l == r){
        cnt[u] = 1, siz[u] = 1, fa[u] = f, key[u] = l-1;
        return u;
    }
    ch[u][0] = build(l, mid-1, u);
    ch[u][1] = build(mid+1, r, u);
    cnt[u] = 1, siz[u] = 1, fa[u] = f, key[u] = mid-1;
    update(u);
    return u;
}

void dfs(int x){
    if(!x) return;
    pushdown(x);
    dfs(ch[x][0]);
    if(key[x]>=1 && key[x]<=n) printf("%d ", key[x]);
    dfs(ch[x][1]);
}

int main(){
    scanf("%d %d", &n, &m);
    //for(int i=0; i<=n+1; ++i) Insert(i);
    root = build(1, n+2, 0);
    while(m--){
        int l, r;
        scanf("%d %d", &l, &r);
        change(l, r);
    }
    dfs(root);
    return 0;
}

 

posted on 2018-03-01 19:01  lazzzy  阅读(102)  评论(0编辑  收藏  举报

导航