NKOJ P1922 第K小数【Splay】

题目描述

现在已有 N 个整数,你有以下三种操作(相同的数视为一个数):
1. A 表示加入一个值为 A 的整数
2. B 表示删除其中值为 B 的整数
3. K 表示输出这些整数中第 K 小的数

输入格式

第一行,两个整数 N M ,表示最开始有 N 个整数,总共有 M 个操作
第二行用空格隔开的 N 个整数
接下来 M 行,每行表示一个操作

输出格式

若干行,一行一个整数,表示所求的第 K 小的数字


S p l a y 板子题也没什么好讲的,就当作一个模板码着吧。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define SG string
#define DB double
#define LL long long
using namespace std;
const int Max=3e6+5;
int N,M,Cnt=1,Root,Fa[Max],Key[Max],Size[Max],CH[Max][2];
inline LL Read(){
    LL X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(LL X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
void Set(int X,int _Key,int _Size,int _Fa){
    Key[X]=_Key;Size[X]=_Size;
    Fa[X]=_Fa;CH[X][0]=CH[X][1]=0;
}
void PushUp(int X){
    Size[X]=Size[CH[X][0]]+Size[CH[X][1]]+1;
}
void Rotate(int X,int P){
    int Y=Fa[X];
    CH[Y][!P]=CH[X][P];
    Fa[CH[X][P]]=Y;Fa[X]=Fa[Y];
    if(Fa[X]){
        CH[Fa[X]][CH[Fa[X]][1]==Y]=X;
    }CH[X][P]=Y;Fa[Y]=X;
    PushUp(Y);PushUp(X);
}
void Splay(int X,int To){
    while(Fa[X]!=To){
        if(Fa[Fa[X]]==To){
            Rotate(X,CH[Fa[X]][0]==X);
        } else {
            int Y=Fa[X],Z=Fa[Y];
            int P=(CH[Z][0]==Y);
            if(CH[Y][P]==X){
                Rotate(X,!P);Rotate(X,P);
            } else {
                Rotate(Y,P);Rotate(X,P);
            }
        }
    }
    if(To==0){
        Root=X;
    }
}
void Insert(int _Key){
    if(!Root){
        Set(Root=Cnt++,_Key,1,0);
    } else {
        int X=Root,Y=0;
        while(X){
            Y=X;X=CH[X][_Key>Key[X]];
        }Set(X=Cnt++,_Key,1,Y);
        CH[Y][_Key>Key[Y]]=X;Splay(X,0);
    }
}
void Delete(int X){
    int Y=CH[X][0];
    while(CH[Y][1]){
        Y=CH[Y][1];
    }
    int Z=CH[X][1];
    while(CH[Z][0]){
        Z=CH[Z][0];
    }
    if(!Y&&!Z){
        Root=0;return;
    } else if (!Y){
        Splay(Z,0);CH[Z][0]=0;PushUp(Z);return;
    } else if (!Z){
        Splay(Y,0);CH[Y][1]=0;PushUp(Y);return;
    }
    Splay(Y,0);Splay(Z,Y);
    CH[Z][0]=0;PushUp(Z);PushUp(Y);
}
int Find(int _Key){
    int X=Root;
    while(X&&Key[X]!=_Key){
        X=CH[X][_Key>Key[X]];
    }
    if(X){
        Splay(X,0);
    }
    return X;
}
int GetKth(int K){
    if(!Root){
        return 0;
    }
    int X=Root;
    while(X){
        if(K==Size[CH[X][0]]+1){
            break;
        }
        if(K>Size[CH[X][0]]+1){
            K-=Size[CH[X][0]]+1;
            X=CH[X][1];
        } else {
            X=CH[X][0];
        }
    }Splay(X,0);
    return Key[X];
}
int main(){
    int I,J,K;
    N=Read(),M=Read();
    for(I=1;I<=N;I++){
        int X=Read();
        if(Find(X)==0){
            Insert(X);
        }
    }
    for(I=1;I<=M;I++){
        int X=Read(),Y=Read();
        if(X==1){
            if(Find(Y)==0){
                Insert(Y);
            }
        } else if (X==2){
            int Z=Find(Y);
            if(Z!=0){
                Delete(Z);
            }
        } else {
            if(Size[Root]<Y){
                puts("0");
            } else {
                Write(GetKth(Y)),putchar('\n');
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81067595