参考题目:LOJ107
解析:
联赛完后统一更模板题题解。
指针版本的代码在这里.
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
int getint(){
re int num;
re char c;
re bool f=0;
while(!isdigit(c=gc()))f^=c=='-';num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return f?-num:num;
}
inline
void outint(int a){
static char ch[13];
if(a==0)pc('0');
if(a<0)pc('-'),a=-a;
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs int N=300005;
struct SPLAY{
int son[N][2];
#define lc(k) son[k][0]
#define rc(k) son[k][1]
int val[N],fa[N];
int cnt[N],siz[N];
int tot,root;
SPLAY():tot(0),root(0){}
bool which(int k){
return k==rc(fa[k]);
}
void update(int k){
siz[k]=(lc(k)?siz[lc(k)]:0)+(rc(k)?siz[rc(k)]:0)+cnt[k];
}
void init(int k){
lc(k)=rc(k)=fa[k]=0;
siz[k]=cnt[k]=1;
}
void clear(int k){
lc(k)=rc(k)=0;
val[k]=siz[k]=cnt[k]=0;
}
void Rotate(int now){
int Fa=fa[now];
bool pos=!which(now);
son[Fa][!pos]=son[now][pos];
if(son[now][pos])fa[son[now][pos]]=Fa;
if(fa[now]=fa[Fa])son[fa[now]][which(Fa)]=now;
fa[Fa]=now;
son[now][pos]=Fa;
update(Fa);
update(now);
if(!fa[now])root=now;
}
void Splay(int now,int to=0){
for(int Fa=fa[now];(Fa=fa[now])!=to;Rotate(now))
if(fa[Fa]!=to)Rotate((which(now)==which(Fa))?Fa:now);
}
void Insert(cs int &key){
if(!root){
init(root=++tot);
val[root]=key;
return ;
}
int now=root,Fa;
for(;;Fa=now,now=son[now][key>val[now]]){
if(!now){
init(now=++tot);
fa[now]=Fa;
val[now]=key;
son[Fa][key>val[Fa]]=now;
return Splay(now);
}
if(val[now]==key){
++cnt[now];
Splay(now);
return ;
}
}
}
int find(cs int &key){
int now=root;
while(now&&val[now]!=key)now=son[now][key>val[now]];
if(now)Splay(now);
return now;
}
int pre_pos(cs int &key){
int now=find(key);
re bool flag=false;
if(!now){
Insert(key);
now=root;
flag=true;
}
if(!lc(now)){
if(flag)Delete(key);
return 0;
}
for(now=lc(now);rc(now);now=rc(now));
if(flag)Delete(key);
return now;
}
void Delete(cs int &key){
int now=find(key);
if(!now)return ;
if(cnt[now]>1){
--cnt[now];
--siz[now];
return ;
}
if(!lc(now)&&!rc(now)){
clear(now);
root=0;
return ;
}
if(!lc(now)){
root=rc(now);
fa[rc(now)]=0;
clear(now);
return;
}
if(!rc(now)){
root=lc(now);
fa[lc(now)]=0;
clear(now);
return ;
}
int res_pre=pre_pos(val[now]);
int res=root;
Splay(res_pre);
rc(root)=rc(res);
fa[rc(res)]=root;
update(root);
}
int querykth(int key){
re int ans=0;
re int res;
re int now=root;
while(true){
if(lc(now)&&key<=siz[lc(now)]){
now=lc(now);
continue;
}
res=(lc(now)?siz[lc(now)]:0)+cnt[now];
if(key<=res)return val[now];
key-=res;
now=rc(now);
}
}
int queryrank(cs int &key){
int now=find(key);
re bool flag=false;
if(!now){
Insert(key);
flag=true;
}
int ans=siz[root];
if(rc(root))ans-=siz[rc(root)];
ans-=cnt[root];
if(flag)Delete(key);
return ans;
}
int querypre(cs int &key){
int now=find(key);
re bool flag=false;
if(!now){
Insert(key);
now=root;
flag=true;
}
if(!lc(now)){
if(flag)Delete(key);
return -1;
}
for(now=lc(now);rc(now);now=rc(now));
if(flag)Delete(key);
return val[now];
}
int querysuf(cs int &key){
int now=find(key);
re bool flag=false;
if(!now){
Insert(key);
now=root;
flag=true;
}
if(!rc(now)){
if(flag)Delete(key);
return -1;
}
for(now=rc(now);lc(now);now=lc(now));
if(flag)Delete(key);
return val[now];
}
}splay;
int n;
signed main(){
n=getint();
while(n--){
int op=getint(),x=getint();
switch(op){
case 0:{splay.Insert(x);break;}
case 1:{splay.Delete(x);break;}
case 2:{outint(splay.querykth(x)),pc('\n');break;}
case 3:{outint(splay.queryrank(x)),pc('\n');break;}
case 4:{outint(splay.querypre(x)),pc('\n');break;}
case 5:{outint(splay.querysuf(x)),pc('\n');break;}
}
}
return 0;
}