题目描述:https://www.luogu.org/problem/P2596

 

解析:首先以位置建立splay。对于1操作,将x旋至根,将x的左儿子与该点的后继相连即可。对于2操作同理。对于3操作,若t为0,不变,其他本质上相当于该点与前或后交换位置。假设现在与前交换位置,可将该点旋至根,再将该点的前驱旋至该点的左儿子,互相交换即可。与后交换位置同理。对于4.5操作,直接找即可。

细节:1.当一个点变成另一个点的儿子时,一定要记得更新这个点的fa。2.每次相连操作或交换操作时,要记得更新size

 

附上代码:

#include<cstdio>
#include<iostream>
#include<map>
#include<climits>
using namespace std;

const int MAXN=80005;
int n,m;
int val[MAXN];
struct Node{
    int son[2],fa,size,val;
}node[MAXN];
int root;
int ndnum=0;
int mp[MAXN];

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

int new_node(int val){
    int x=++ndnum;
    node[x].fa=node[x].son[0]=node[x].son[1]=0;
    node[x].size=1;node[x].val=val;
    if(val>0) mp[val]=x;
    return x;
}

void update(int x){
    node[x].size=node[node[x].son[0]].size+node[node[x].son[1]].size+1;
}

int buildtree(int l,int r){
    if(l>r) return 0;
    if(l==r) return new_node(val[l]);
    int mid=(l+r)>>1,x=new_node(val[mid]);
    node[x].son[0]=buildtree(l,mid-1);node[x].son[1]=buildtree(mid+1,r);
    node[node[x].son[0]].fa=x;node[node[x].son[1]].fa=x;
    update(x);
    return x;
}

int check(int x){
    return x==node[node[x].fa].son[1];
}

void rotate(int x){
    int y=node[x].fa,z=node[y].fa,d=check(x),xx=node[x].son[d^1];
    node[y].son[d]=xx;node[xx].fa=y;
    node[z].son[check(y)]=x;node[x].fa=z;
    node[x].son[d^1]=y;node[y].fa=x;
    update(y);update(x);
}

void splay(int x,int to=0){
    while(node[x].fa!=to){
        int y=node[x].fa,z=node[y].fa;
        if(z!=to)
            rotate(check(x)==check(y)?y:x);
        rotate(x);
    }
    if(!to)
        root=x;
}

void move_to_first(int x){
    splay(x);
    if(!node[x].son[0]) return;
    if(!node[x].son[1]){
        swap(node[x].son[0],node[x].son[1]);
        return;
    }
    int lson=node[x].son[0],tmp=node[x].son[1];
    while(node[tmp].son[0]) tmp=node[tmp].son[0];
    node[lson].fa=tmp;node[tmp].son[0]=lson;node[x].son[0]=0;
    splay(lson);  
}

void move_to_last(int x){
    splay(x);
    if(!node[x].son[1]) return;
    if(!node[x].son[0]){
        swap(node[x].son[0],node[x].son[1]);
        return;
    }
    int rson=node[x].son[1],tmp=node[x].son[0];
    while(node[tmp].son[1]) tmp=node[tmp].son[1];
    node[rson].fa=tmp;node[tmp].son[1]=rson;node[x].son[1]=0;
    splay(rson);
}

void change(int x,int y){
    splay(x);
    if(y==-1){
        int lson=node[x].son[0];
        if(!lson) return;    
        while(node[lson].son[1]) lson=node[lson].son[1];
        splay(lson,x);
        int lson_lson=node[lson].son[0],lson_rson=node[lson].son[1];
        node[lson].son[0]=x;node[x].fa=lson;
        node[lson].son[1]=node[x].son[1];node[node[x].son[1]].fa=lson;
        node[x].son[0]=lson_lson;node[lson_lson].fa=x;
        node[x].son[1]=lson_rson;node[lson_rson].fa=x;
        node[lson].fa=0;
        update(x);update(lson);
        root=lson;
    } 
    if(y==1){
        int rson=node[x].son[1];
        if(!rson) return;
        while(node[rson].son[0]) rson=node[rson].son[0];
        splay(rson,x);
        int rson_lson=node[rson].son[0],rson_rson=node[rson].son[1];
        node[rson].son[0]=node[x].son[0];node[node[x].son[0]].fa=rson;
        node[rson].son[1]=x;node[x].fa=rson;
        node[x].son[0]=rson_lson;node[rson_lson].fa=x;
        node[x].son[1]=rson_rson;node[rson_rson].fa=x;
        node[rson].fa=0;
        update(x);update(rson);
        root=rson;
    }
}

int query(int x){
    splay(x);
    return node[node[x].son[0]].size;
}

int find(int kth){
    int cur=root;
    while(1){
        if(kth<=node[node[cur].son[0]].size)
            cur=node[cur].son[0];
        else{
            kth-=node[node[cur].son[0]].size+1;
            if(!kth) return cur;
            cur=node[cur].son[1];
        }
    }
}

void write(int x){
    if(node[x].son[0]) write(node[x].son[0]);
    cout<<node[x].val<<' ';
    if(node[x].son[1]) write(node[x].son[1]);
}

int main(){
    n=read();m=read();
    for(int i=1;i<=n;++i) val[i]=read();
    root=buildtree(1,n);
    while(m--){
        char opt[15];
        scanf("%s",opt+1);
        if(opt[1]=='T'){
            int x=read();
            move_to_first(mp[x]);
        }
        else if(opt[1]=='B'){
            int x=read();
            move_to_last(mp[x]);
        }
        else if(opt[1]=='I'){
            int x=read(),y=read();
            if(y==0) continue;
            change(mp[x],y);
        }
        else if(opt[1]=='A'){
            int x=read();
            printf("%d\n",query(mp[x]));
        }
        else{
            int x=read();
            printf("%d\n",node[find(x)].val);
        }
    }
    return 0;
}
View Code