JOYOI1728 普通平衡树(Splay)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengwill97/article/details/79949988

题意分析

Splay 模板题,理解了好半天,照猫画虎来一发。
我写的这个效率很低啊,跑了400ms。。。

代码总览

#include<bits/stdc++.h>
using namespace std;
const int nmax = 100000<<2;
int ch[nmax][2], f[nmax], cnt[nmax], key[nmax], size[nmax];
int root = 0, sz = 0;
inline void clear(int x) {
    ch[x][0] = ch[x][1] = f[x] = cnt[x] = key[x] = size[x] = 0;
}
inline int get(int x) {
    return ch[f[x]][1] == x;
}
inline void update(int x) {
    if(x){
        size[x] = cnt[x];
        if(ch[x][0]) size[x] += size[ch[x][0]];
        if(ch[x][1]) size[x] += size[ch[x][1]];
    }
}
inline void rotate(int x) {
    int old = f[x], oldf = f[old], which = get(x);
    ch[old][which] = ch[x][which^1]; f[ch[old][which]] = old;
    f[old] = x; ch[x][which^1] = old;
    f[x] = oldf;
    if(oldf) ch[oldf][ch[oldf][1] == old] = x;
    update(old);update(x);
}
inline void splay(int x) {
    for(int fa; fa = f[x]; rotate(x))
        if(f[fa]) rotate((get(x) == get(fa))? fa:x);
    root = x;
}
inline void insert(int v) {
    if(root == 0) {
        sz ++; ch[sz][0] = ch[sz][1] = f[sz] = 0;
        key[sz] = v; cnt[sz] = 1; size[sz] = 1;
        root = sz; return;
    }
    int now = root,  fa = 0;
    while(1) {
        if(key[now] == v) {
            cnt[now] ++; update(now); update(fa);
            splay(now); break;
        }
        fa = now;
        now = ch[now][v > key[now]];
        if(now == 0) {
            sz ++;
            ch[sz][0] = ch[sz][1] = 0; key[sz] = v; size[sz] = 1;
            cnt[sz] = 1; f[sz] = fa; ch[fa][v > key[fa]] = sz;
            update(fa);
            splay(sz);
            break;
        }
    }
}
inline int find(int v) {
    int ans = 0, now = root;
    while(1) {
        if(v < key[now]) now = ch[now][0];
        else {
            ans += (ch[now][0]? size[ch[now][0]]:0);
            if(v == key[now]) {splay(now); return ans + 1;}
            ans += cnt[now];
            now = ch[now][1];
        }
    }
}
inline int findx(int x) {
    int now = root;
    while(1) {
        if(ch[now][0] &&  x<=size[ch[now][0]]) now = ch[now][0];
        else {
            int temp = (ch[now][0]?size[ch[now][0]]:0) + cnt[now];
            if(x <= temp) return key[now];
            x -= temp; now = ch[now][1];
        }
    }
}
inline int pre() {
    int now = ch[root][0];
    while (ch[now][1]) now = ch[now][1];
    return now;
}
inline int next(){
    int now = ch[root][1];
    while (ch[now][0]) now = ch[now][0];
    return now;
}

inline void del(int x){
     int whatever = find(x);
     if (cnt[root]>1) {cnt[root]--;return;}
     if (!ch[root][0]&&!ch[root][1]) {clear(root);root=0;return;}
     if (!ch[root][0]){
          int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;
     }
     else if (!ch[root][1]){
          int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;
     }
     int leftbig=pre(),oldroot=root;
     splay(leftbig);
     f[ch[oldroot][1]]=root;
     ch[root][1]=ch[oldroot][1];
     clear(oldroot);
     update(root);
     return;
}
int n,opt,x;
int main(){
    scanf("%d",&n);
    for(int i = 0;i<n;++i){
        scanf("%d %d",&opt,&x);
        if(opt == 1) insert(x);
        else if(opt == 2) del(x);
        else if(opt == 3) printf("%d\n",find(x));
        else if(opt == 4) printf("%d\n",findx(x));
        else if(opt == 5) {
            insert(x); printf("%d\n",key[pre()]); del(x);
        }else if(opt == 6){
            insert(x); printf("%d\n",key[next()]); del(x);
        }
    }
    return 0;
}
阅读更多

没有更多推荐了,返回首页