Splay(单点修改+查询)

仅供参考。。。

#include<bits/stdc++.h>
using namespace std;

char readc(){
    static char buf[100000], *l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF;else return *l++;
}

int read(){
    int x=0,f=1;char ch=readc();
    while (!isdigit(ch)) { if (ch=='-') f=-1; ch=readc();}
    while (isdigit(ch)) x=x*10+ch-48,ch=readc();
    return x*f;
}

namespace splay {

    const int MAXN=100000+11;
    int fa[MAXN],ch[MAXN][2],val[MAXN],siz[MAXN],num[MAXN],root,cnt;
    void clear(int x) {
        fa[x]=val[x]=siz[x]=num[x]=ch[x][0]=ch[x][1]=0;
    }
    void update(int x) {
        siz[x]=(ch[x][0] ? siz[ch[x][0]]:0)+(ch[x][1] ? siz[ch[x][1]]:0)+num[x];
    }
    int succ() {
        int x=ch[root][1];
        while (ch[x][0]) x=ch[x][0];
        return val[x];
    }
    int succ_id() {
        int x=ch[root][1];
        while (ch[x][0]) x=ch[x][0];
        return x;
    }
    int pre() {
        int x=ch[root][0];
        while (ch[x][1]) x=ch[x][1];
        return val[x];
    }
    int pre_id() {
        int x=ch[root][0];
        while (ch[x][1]) x=ch[x][1];
        return x;
    }
    void rotate(int x) {
        int y=fa[x],z=fa[y],d=(ch[y][1]==x);
        ch[y][d]=ch[x][d^1];
        fa[ch[x][d^1]]=y;
        ch[x][d^1]=y;
        fa[y]=x,fa[x]=z;
        if (z)ch[z][ch[z][1]==y]=x;
        update(y);
        update(x);
    }
    void splay(int x) {
        for (int y; y=fa[x]; rotate(x))
            if (fa[y])
                rotate((x==ch[y][0])^(y==ch[fa[y]][0]) ? x:y);
        root=x;
    }
    int find_val(int x) { // 查询排名为 x 的数
        int y=root,tmp;
        while (true) {
            if (ch[y][0]&&siz[ch[y][0]]>=x) y=ch[y][0];
            else {
                tmp=(ch[y][0] ? siz[ch[y][0]]:0)+num[y];
                if (x<=tmp) return val[y];
                x-=tmp,y=ch[y][1];
            }
        }
    }
    int find_rank(int x) { // 查询 x 数的排名
        int y=root,tmp=0;
        while (true){
            if (x<val[y]) y=ch[y][0];
            else {
                tmp+=(ch[y][0] ? siz[ch[y][0]]:0);
                if (x==val[y]){
                    splay(y);
                    return tmp+1;
                }
                tmp+=num[y],y=ch[y][1];
            }
        }
    }
    void insert(int k) {
        int x=root;
        if (!x) {
            root=x=++cnt,ch[x][0]=ch[x][1]=fa[x]=0,val[x]=k,num[x]=siz[x]=1;
            return;
        }
        int y=x,z=0;
        while (true) {
            if (val[y]==k) {
                num[y]++;update(y),update(z);splay(y);
                break;
            }
            z=y,y=ch[y][val[y]<k];
            if (!y) {
                val[y=++cnt]=k;num[y]=siz[y]=1;ch[y][0]=ch[y][1]=0;fa[y]=x;ch[x][val[x]<k]=y;
                break;
            }
            x=y;
        }
        splay(y);
    }
    void delt(int k) {
        find_rank(k);
        int x=root;
        if (!x)
            return;
        if (num[x]>1) {
            num[x]--,siz[x]--;
            return;
        }
        if (!ch[x][0]&&!ch[x][1]) {
            clear(x);root=0;
            return;
        }
        if (!ch[x][0]||!ch[x][1]) {
            int y=max(ch[x][0],ch[x][1]);
            root=y,fa[y]=0;clear(x);
            return;
        }
        int tmp=pre_id();
        splay(tmp);fa[ch[x][1]]=tmp;ch[tmp][1]=ch[x][1];clear(x);update(tmp);
    }

}
using namespace splay;

int main() {
    int n=read();
    while (n--) {
        int opt=read(),x=read();
        switch(opt) {
            case 1: insert(x); break;
            case 2: delt(x); break;
            case 3: printf("%d\n",find_rank(x)); break;
            case 4: printf("%d\n",find_val(x)); break;
            case 5: insert(x),printf("%d\n",pre()),delt(x); break;
            case 6: insert(x),printf("%d\n",succ()),delt(x); break;
        }
    }
    return 0;
}

 

posted @ 2018-08-24 12:29  QingCai_DCF  阅读(342)  评论(0编辑  收藏  举报