题意:有一个n的序列(n<=1e8),有三操作,操作Q次
1.把第x个人放到队伍的前面
2.查询第x个人的位置
3.查询第x个位置是哪个人
思路:因为n比较大,Q比较小,所以选择记录一次啊出现了哪些数,Splay中每个位置记录一下之前有多少个数是不会被用到的
对于操作1,我们标记一下x在Splay中的下标的位置,
对于操作2,就是x为根的Splay树中左孩子的size
对于操作3,就是第k大(这个第k大最大就为k)
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
#define key_value ch[ch[root][1]][0]
const int N=3e5+100;
int a[N];
struct node{
int op,x;
}Q[N];
int root,size[N],ch[N][2],fa[N],cnt[N],val[N],n,tot,cnt1;//分别表示根,子树结点数量,左右孩子(0为左孩子,1为右孩子),翻转标记
map<int,int>mp;
void pushup(int x){
size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
void Newnode(int &now,int father,int k,int Count){
now=++tot;
fa[now]=father;
ch[now][0]=ch[now][1]=0,val[now]=k,cnt[now]=Count,mp[k]=now;
size[now]=Count;
}
void build(int &now,int l,int r,int father){
if(l>r)
return ;
int m=(l+r)>>1;
Newnode(now,father,a[m],a[m]-a[m-1]);
build(ch[now][0],l,m-1,now);
build(ch[now][1],m+1,r,now);
pushup(now);
}
void init(){
sort(a+1,a+cnt1+1);
cnt1=unique(a+1,a+cnt1+1)-a-1;
root=tot=0;
Newnode(root,0,INF,1);
Newnode(ch[root][1],root,INF,1);//头尾各加入一个空位
build(key_value,1,cnt1,ch[root][1]);
pushup(ch[root][1]);
pushup(root);
}
//旋转,kind为1为右旋,kind为0为左旋
void Rotate(int x,int kind){
int y=fa[x];
ch[y][!kind]=ch[x][kind];
fa[ch[x][kind]]=y;
//如果父节点不是根结点,则要和父节点的父节点连接起来
if(fa[y])
ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[x]=fa[y];
ch[x][kind]=y;
fa[y]=x;
pushup(y);
}
//Splay调整,将根为now的子树调整为goal
void Splay(int now,int goal){
while(fa[now]!=goal){
if(fa[ fa[now] ]==goal)
Rotate(now,ch[ fa[now] ][0]==now);
else{
int pre=fa[now],kind=ch[ fa[pre] ][0]==pre; //左儿子为1,右儿子为0
if(ch[pre][kind]==now){ //两个方向不同
Rotate(now,!kind);
Rotate(now,kind);
}
else{ //两个方向相同
Rotate(pre,kind);
Rotate(now,kind);
}
}
}
if(goal==0) root=now;
pushup(now);
}
int get_kth(int x,int k){
int num1=size[ch[x][0]],num2=size[ch[x][0]]+cnt[x];
if(num1<k&&num2>=k)
return val[x]-(num2-k);
else if(num1>=k)
return get_kth(ch[x][0],k);
return get_kth(ch[x][1],k-num2);
}
int get_min(int x){
x=ch[x][1];
while(ch[x][0])
x=ch[x][0];
return x;
}
int get_max(int x){
x=ch[x][0];
while(ch[x][1])
x=ch[x][1];
return x;
}
void remove(){
int m=get_max(root);
Splay(m,root);
ch[m][1]=ch[root][1];
fa[ch[root][1]]=m;
root=m;
fa[root]=0;
pushup(root);
}
void Top(int x){
int Belong=mp[x]; //映射为Splay中的点
int Count=cnt[Belong];
Splay(Belong,0);
remove();
Splay(1,0);
Splay(get_min(root),root);
Newnode(key_value,ch[root][1],x,Count);
pushup(ch[root][1]);
pushup(root);
}
void Query(int x){
int Belong=mp[x];
Splay(Belong,0);
printf("%d\n",size[ch[root][0]]);
}
void Rank(int x){
printf("%d\n",get_kth(root,x+1));
}
char str[10];
void travel(int x){
if(!x) return ;
travel(ch[x][0]);
printf("(%d %d )",val[x],cnt[x]);
travel(ch[x][1]);
}
int main(){
int _,m,x;
scanf("%d",&_);
for(int case1=1;case1<=_;++case1){
printf("Case %d:\n",case1);
cnt1=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%s%d",str,&Q[i].x);
if(str[0]=='T') Q[i].op=1;
else if(str[0]=='Q') Q[i].op=2;
else Q[i].op=3;
a[++cnt1]=Q[i].x,a[++cnt1]=Q[i].x+1;
if(Q[i].x!=1)
a[++cnt1]=Q[i].x-1;
}
init();
for(int i=1;i<=m;i++){
if(Q[i].op==1) Top(Q[i].x);
else if(Q[i].op==2) Query(Q[i].x);
else Rank(Q[i].x);
}
}
return 0;
}