HNOID1每道题都已小于2s的差距领先ljss交到BZ上23333
论快捷键提交的优越性
考虑一次插入了x,x的前驱为pre,后继为nxt,平衡树中排名相邻的两个点一定互为祖先关系,那么如果pre为nxt的祖先,x就插入到了nxt的左儿子,如果nxt为pre的祖先,x就插入到了pre的右儿子
考虑把最小值旋到根的操作,最小值没有左子树,最小值的右子树变成了最小值父亲的左子树,根变成了最小值的右儿子
把最大值旋到根同理
那么用ETT来维护这个spaly即可
ljss告诉我们不用ETT直接写splay来维护dfs序也行
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 400010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
#define tr son[son[rt][1]][0]
char xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
#define isd(c) (c>='0'&&c<='9')
int read(){
char xchh;
int xaa;
while(xchh=getc(),!isd(xchh));(xaa=xchh-'0');
while(xchh=getc(),isd(xchh))xaa=xaa*10+xchh-'0';return xaa;
}
int m;
map<int,int>L,R;
set<int>S;
int tot;
int fa[MAXN],son[MAXN][2],v[MAXN],sum[MAXN];
int rt;
void tpt(){
int i;
cerr<<rt<<"!!!"<<endl;
for(i=1;i<=tot;i++){
cerr<<i<<':'<<son[i][0]<<' '<<son[i][1]<<' '<<fa[i]<<'#'<<v[i]<<' '<<sum[i]<<endl;
}
cerr<<endl;
}
inline void ud(int x){
sum[x]=v[x]+sum[son[x][0]]+sum[son[x][1]];
}
inline void cot(int x,int y,bool z){
if(x){
fa[x]=y;
}
if(y){
son[y][z]=x;
}
}
inline void rot(int x,bool z){
int xx=fa[x],xxx=fa[xx];
cot(son[x][z],xx,z^1);
cot(x,xxx,son[xxx][1]==xx);
cot(xx,x,z);
ud(xx);
}
void splay(int x,int y){
int xx=fa[x],xxx=fa[xx];
while(xx!=y){
if(xxx==y){
rot(x,son[xx][0]==x);
}else{
bool z=son[xxx][0]==xx;
if(son[xx][z]==x){
rot(x,z^1);
rot(x,z);
}else{
rot(xx,z);
rot(x,z);
}
}
xx=fa[x],xxx=fa[xx];
}
ud(x);
if(!y){
rt=x;
}
}
void ins(){
tr=tot-1;
son[tr][1]=tot;
fa[son[tr][1]]=tr;
fa[tr]=son[rt][1];
ud(son[tr][1]);
ud(tr);
ud(son[rt][1]);
ud(rt);
}
void ins1(int x){
splay(x,0);
int t=son[rt][1];
while(son[t][0]){
t=son[t][0];
}
splay(t,rt);
ins();
}
void ins2(int x){
splay(x,0);
int t=son[rt][0];
while(son[t][1]){
t=son[t][1];
}
splay(t,0);
ins();
}
int ask(int x){
splay(x,0);
return sum[son[x][0]]+v[x];
}
void del(int x){
splay(x,0);
if(!son[x][0]){
rt=son[x][1];
fa[rt]=0;
return ;
}
if(!son[x][1]){
rt=son[x][0];
fa[rt]=0;
return ;
}
if(!son[x][0]&&!son[x][1]){
rt=0;
return ;
}
int t=son[x][0];
while(son[t][1]){
t=son[t][1];
}
splay(t,rt);
son[t][1]=son[rt][1];
fa[son[rt][1]]=t;
ud(t);
rt=t;
fa[rt]=0;
}
void toins(int l,int r){
son[l][0]=son[r][1]=0;
son[r][0]=rt;
son[l][1]=r;
fa[rt]=r;
fa[r]=l;
ud(r);
ud(l);
rt=l;
fa[rt]=0;
}
int main(){
int o,x;
set<int>::iterator it,itp,itn;
m=read();
while(m--){
o=read();
if(o==1){
x=read();
v[L[x]=++tot]=1;
v[R[x]=++tot]=-1;
it=(S.insert(x)).first;
if(S.size()==1){
rt=tot-1;
fa[tot]=tot-1;
son[tot-1][1]=tot;
ud(tot);
ud(tot-1);
}else if(it==S.begin()){
ins1(L[*(++it)]);
}else if(it==(--S.end())){
ins2(R[*(--it)]);
}else{
itn=itp=it;
int pre=L[*(--itp)],nxt=L[*(++itn)];
if(ask(pre)<ask(nxt)){
ins2(nxt+1);
}else{
ins1(pre);
}
}
printf("%d\n",ask(tot-1));
}
if(o==2){
int l=L[*S.begin()],r=R[*S.begin()];
printf("%d\n",ask(l));
del(l);
del(r);
toins(l,r);
}
if(o==3){
int l=L[*(--S.end())],r=R[*(--S.end())];
printf("%d\n",ask(l));
del(l);
del(r);
toins(l,r);
}
if(o==4){
int l=L[*S.begin()],r=R[*S.begin()];
S.erase(S.begin());
printf("%d\n",ask(l));
del(l);
del(r);
}
if(o==5){
int l=L[*(--S.end())],r=R[*(--S.end())];
S.erase(--S.end());
printf("%d\n",ask(l));
del(l);
del(r);
}
}
return 0;
}
/*
5
1 95
1 54
1 51
2
3
*/