[ZJOI2006]书架

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

int n,q,a,b;
string tp;
int date[MAXN],bianhao[MAXN];
struct Splay{
    int num[MAXN],ch[MAXN][2],sz[MAXN],f[MAXN],cnt[MAXN],rt,tot,tag[MAXN];
    int get(int x){
        return (x==ch[f[x]][1]);
    }
    int up(int x){
        sz[x] = cnt[x];
        if(ch[x][0])sz[x] = sz[x]+sz[ch[x][0]];
        if(ch[x][1])sz[x] = sz[x]+sz[ch[x][1]];
        return 0;
    }
    int rote(int x){
        int y = f[x],z = f[y],k = get(x),p = get(y);
        if(y==0)return 0;
        if(z)ch[z][p] = x;
        if(ch[x][k^1])f[ch[x][k^1]] = y;
        ch[y][k] = ch[x][k^1];
        ch[x][k^1] = y;
        f[x] = z;
        f[y] = x;
        up(y);up(x);
        return 0;
    }
    int splay(int x){
        for(int y = f[x];(y = f[x]);rote(x)){
            rote((get(x)==get(y))?y:x);
        }
        rt = x;
        return 0;
    }
    int rank(int x){
        int now=rt,ans=1;
        while(1){
            if(num[now]<=x){
                ans =     ans+sz[ch[now][0]];
                if(num[now]==x){
                splay(now);
                return ans;
                }
                ans = ans+cnt[now];
                now = ch[now][1];
            }
            else{
                now = ch[now][0];
            }
        }
    }
    int pre(){//前继 比她小的最大 
        int now = ch[rt][0];
        while(ch[now][1])now = ch[now][1];
        return now;
    }
    int suc(){
        int now = ch[rt][1];
        while(ch[now][0])now = ch[now][0];
        return now;
    }
    int add(int x){
        int now = rt;
        while(1){
            if(num[now]==x){
                cnt[now]++;
                splay(now);
                return 0;
            }
            int to = (num[now]<x);
            if(!ch[now][to]){
                tot++;
                ch[now][to] = tot;
                num[tot] = x;
                f[tot] = now;
                cnt[tot] = 1;
                sz[tot] = 1;
                splay(tot);
                return 0;
            }
            else now = ch[now][to];
        }
    }
    int kth(int x){
        int now =rt;
        while(1){
            if(sz[ch[now][0]]<x&&ch[now][0]){
                x = x-sz[ch[now][0]];
                if(x<=cnt[now])return now;
                x = x-cnt[now];
                now = ch[now][1];
            }
            else if(!ch[now][0]){
                if(x<=cnt[now])return now;
                x = x-cnt[now];
                now = ch[now][1];
            }
            else{
                now = ch[now][0];
            }
        }
    }
    int del(int x){
        splay(x);
        int fu = pre(),ck = suc();
        if(fu==0){
            int hj = ch[rt][1];
            ch[rt][0] = ch[rt][1] = f[rt] = 0;
            rt = hj;
            return 0;
        }
        if(ck==0){
            int hj = ch[rt][0];
            ch[rt][0] = ch[rt][1] = f[rt] = 0;
            rt = hj;
            return 0;
        }
        splay(fu);
        splay2(ck);
        ch[ch[ck][0]][0] = ch[ch[ck][0]][1] = f[ch[ck][0]] = 0;
        ch[ck][0] = 0;
        up(ch[ck][1]);
        up(fu);
    }
    int chajinqu(int x,int y){
        if(y==0)return 0;
        splay(x);
        int fu = pre(),ck = suc();
        if(y==1&&ck!=0){
        swap(bianhao[date[rt]],bianhao[date[ck]]);
        swap(date[rt],date[ck]);
        swap(num[rt],num[ck]);
        }
        else if(fu!=0){
        swap(bianhao[date[rt]],bianhao[date[fu]]);
        swap(date[rt],date[fu]);
        swap(num[rt],num[fu]);        
        }
        
    }
    int splay2(int x){
        for(int y = f[x];(y = f[x])!=rt;rote(x)){
            if(f[y]!=rt)rote((get(x)==get(y))?y:x);
        }
        return 0;
    }
    int minl(){
        int now = rt;
        while(ch[now][0])now = ch[now][0];
        return now;
    }
    int maxl(){
        int now = rt;
        while(ch[now][1])now = ch[now][1];
        return now;
    }
}T;

int main(){
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        cin>>date[i];
        bianhao[date[i]] = i;
        T.add(i);
    }
    //知道了每个树节点所对于的书本编号....
    for(int i=1;i<=q;i++){
        cin>>tp;
        if(tp=="Top"){
            cin>>a;//把ma所对应的树的节点删掉,然后在树的最左插入... 
            T.del(bianhao[a]);
            if(T.minl()==0){
            T.ch[T.rt][0] = bianhao[a];
            T.f[bianhao[a]] = T.rt;
            T.up(bianhao[a]);T.up(T.rt);    
            }
            else{
            T.splay(T.minl());
            T.ch[T.rt][0] = bianhao[a];
            T.f[bianhao[a]] = T.rt;
            T.up(bianhao[a]);T.up(T.rt);    
            }
        }
        else if(tp=="Bottom"){
            cin>>a;//把ma所对应的树的节点删掉,然后在树的最右插入... 
            T.del(bianhao[a]);
            if(T.maxl()==0){
            T.ch[T.rt][1] = bianhao[a];
            T.f[bianhao[a]] = T.rt;
            T.up(bianhao[a]);T.up(T.rt);    
            }
            else{
            T.splay(T.maxl());
            T.ch[T.rt][1] = bianhao[a];
            T.f[bianhao[a]] = T.rt;
            T.up(bianhao[a]);T.up(T.rt);    
            }
        }
        else if(tp=="Insert"){
            //这里炸了 
            cin>>a>>b;
            T.chajinqu(bianhao[a],b);
        }
        else if(tp=="Ask"){
            cin>>a;
            T.splay(bianhao[a]);
            printf("%d
",T.sz[T.ch[T.rt][0]]);
        }
        else if(tp=="Query"){
            cin>>a;
            printf("%d
",date[T.kth(a)]);
        }
    } 
}
View Code

有空来调,好毒....

好吧这个是ac代码(我可没看题解)

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

int n,q,a,b;
string tp;
int date[MAXN],bianhao[MAXN];
struct Splay{
    int num[MAXN],ch[MAXN][2],sz[MAXN],f[MAXN],cnt[MAXN],rt,tot,tag[MAXN];
    int get(int x){
        return (x==ch[f[x]][1]);
    }
    int up(int x){
        sz[x] = cnt[x];
        if(ch[x][0])sz[x] = sz[x]+sz[ch[x][0]];
        if(ch[x][1])sz[x] = sz[x]+sz[ch[x][1]];
        return 0;
    }
    int rote(int x){
        int y = f[x],z = f[y],k = get(x),p = get(y);
        if(y==0)return 0;
        if(z)ch[z][p] = x;
        if(ch[x][k^1])f[ch[x][k^1]] = y;
        ch[y][k] = ch[x][k^1];
        ch[x][k^1] = y;
        f[x] = z;
        f[y] = x;
        up(y);up(x);
        return 0;
    }
    int splay(int x){
        for(int y = f[x];(y = f[x]);rote(x)){
            rote((get(x)==get(y))?y:x);
        }
        f[x] = 0;
        rt = x;
        return 0;
    }
    int pre(){//前继 比她小的最大 
        int now = ch[rt][0];
        while(ch[now][1])now = ch[now][1];
        return now;
    }
    int suc(){
        int now = ch[rt][1];
        while(ch[now][0])now = ch[now][0];
        return now;
    }
    int add(int x){
        int now = rt;
        if(rt == 0){
            tot++;
            rt = tot;
            num[tot] = x;
            cnt[tot] = 1;
            sz[tot] = 1;
            return 0;
        }
        while(1){
            if(num[now]==x){
                cnt[now]++;
                splay(now);
                return 0;
            }
            int to = (num[now]<x);
            if(!ch[now][to]){
                tot++;
                ch[now][to] = tot;
                num[tot] = x;
                f[tot] = now;
                cnt[tot] = 1;
                sz[tot] = 1;
                splay(tot);
                return 0;
            }
            else now = ch[now][to];
        }
    }
    int kth(int x){
        int now =rt;
        while(1){
            if(sz[ch[now][0]]<x&&ch[now][0]){
                x = x-sz[ch[now][0]];
                if(x<=cnt[now])return now;
                x = x-cnt[now];
                now = ch[now][1];
            }
            else if(!ch[now][0]){
                if(x<=cnt[now])return now;
                x = x-cnt[now];
                now = ch[now][1];
            }
            else{
                now = ch[now][0];
            }
        }
    }
    int del(int x){
        splay(x);
        int fu = pre(),ck = suc();
        if(fu==0){
            int hj = ch[rt][1];
            sz[rt] = 0;
            f[hj] = 0;
            ch[rt][0] = ch[rt][1] = f[rt] = 0;
            rt = hj;
            up(rt);
            return 0;
        }
        if(ck==0){
            int hj = ch[rt][0];
            sz[rt] = 0;
            f[hj] = 0;
            ch[rt][0] = ch[rt][1] = f[rt] = 0;
            rt = hj;
            up(rt);
            return 0;
        }
        splay(fu);
        splay2(ck);
        sz[ch[ck][0]] = 0;
        f[ch[ck][0]] = 0;
        ch[ch[ck][0]][0] = ch[ch[ck][0]][1] = f[ch[ck][0]] = 0;
        ch[ck][0] = 0;
        up(ch[rt][1]);
        up(fu);
    }
    int chajinqu(int x,int y){
        if(y==0)return 0;
        splay(x);
        int fu = pre(),ck = suc();
        if(y==1&&ck!=0){
        swap(bianhao[date[rt]],bianhao[date[ck]]);
        swap(date[rt],date[ck]);
        swap(num[rt],num[ck]);
        }
        else if(y==(-1)&&fu!=0){
        swap(bianhao[date[rt]],bianhao[date[fu]]);
        swap(date[rt],date[fu]);
        swap(num[rt],num[fu]);        
        }
        
    }
    int splay2(int x){
        for(int y = f[x];(y = f[x])!=rt;rote(x)){
            if(f[y]!=rt)rote((get(x)==get(y))?y:x);
        }
        return 0;
    }
    int minl(){
        int now = rt;
        while(ch[now][0])now = ch[now][0];
        return now;
    }
    int maxl(){
        int now = rt;
        while(ch[now][1])now = ch[now][1];
        return now;
    }
}T;

int main(){
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        cin>>date[i];
        bianhao[date[i]] = i;
        T.add(i);
    }
    //知道了每个树节点所对于的书本编号....
    for(int i=1;i<=q;i++){
        cin>>tp;
        if(tp=="Top"){
            cin>>a;//把ma所对应的树的节点删掉,然后在树的最左插入... 
            T.del(bianhao[a]);
            if(T.minl()!=T.rt)T.splay(T.minl());
            T.up(T.rt);    
            T.ch[T.rt][0] = bianhao[a];
            T.sz[bianhao[a]] = 1;
            T.f[bianhao[a]] = T.rt;
            T.up(bianhao[a]);
            T.up(T.rt);    
        }
        else if(tp=="Bottom"){
            cin>>a;//把ma所对应的树的节点删掉,然后在树的最右插入... 
            T.del(bianhao[a]);
            if(T.maxl()!=T.rt)T.splay(T.maxl());
            T.up(T.rt);    
            T.ch[T.rt][1] = bianhao[a];
            T.sz[bianhao[a]] = 1;
            T.f[bianhao[a]] = T.rt;
            T.up(bianhao[a]);
            T.up(T.rt);    
        }
        else if(tp=="Insert"){
            //这里炸了 
            cin>>a>>b;
            T.chajinqu(bianhao[a],b);
        }
        else if(tp=="Ask"){
            cin>>a;
            T.splay(bianhao[a]);
            printf("%d
",T.sz[T.ch[T.rt][0]]);
        }
        else if(tp=="Query"){
            cin>>a;
            printf("%d
",date[T.kth(a)]);
        }
    }
}
View Code

嘛,题目要求很简单,...直接不管BST性质,splay上乱搞区间操作....

原文地址:https://www.cnblogs.com/shatianming/p/12239460.html