欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ3224
题意概括
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
题解
splay模板题。
代码
UPD(2018-03-20):省选一试前夜,抱佛脚打板子,发现之前的代码真丑。注意,在splay中预先放一个非常大的数可以有效的排除平衡树空的特殊情况。我在细节处理上也增加了大量改进,代码量爆缩,运行效率略高了一些,老的那份代码在后面。
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int n,root=1,size=1,val[N],cnt[N],son[N][2],fa[N],tot[N];
int wson(int x){
return son[fa[x]][1]==x;
}
void pushup(int x){
tot[x]=cnt[x]+tot[son[x][0]]+tot[son[x][1]];
}
void rotate(int x){
if (!x)
return;
int y=fa[x],z=fa[y],L=wson(x),R=L^1;
if (z)
son[z][wson(y)]=x;
fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
son[y][L]=son[x][R],son[x][R]=y;
pushup(y),pushup(x);
}
void splay(int x,int k){
if (!x)
return;
if (!k)
root=x;
for (int y=fa[x];fa[x]!=k;rotate(x),y=fa[x])
if (fa[y]!=k)
rotate(wson(x)==wson(y)?y:x);
}
int find(int x,int v){
return val[x]==v?x:find(son[x][v>val[x]],v);
}
int findkth(int x,int k){
if (k<=tot[son[x][0]])
return findkth(son[x][0],k);
k-=tot[son[x][0]];
if (k<=cnt[x])
return x;
k-=cnt[x];
return findkth(son[x][1],k);
}
int findnxt(int x,int v){
if (!x)
return 0;
if (val[x]<=v)
return findnxt(son[x][1],v);
else {
int res=findnxt(son[x][0],v);
return res?res:x;
}
}
int findpre(int x,int v){
if (!x)
return 0;
if (val[x]>=v)
return findpre(son[x][0],v);
else {
int res=findpre(son[x][1],v);
return res?res:x;
}
}
void insert(int &x,int pre,int v){
if (!x){
x=++size;
val[x]=v,cnt[x]=tot[x]=1,fa[x]=pre;
splay(x,0);
return;
}
tot[x]++;
if (val[x]==v){
cnt[x]++;
return;
}
insert(son[x][v>val[x]],x,v);
}
void Insert(int v){insert(root,0,v);}
void Delete(int v){
int x;
splay(x=find(root,v),0);
if (--cnt[x])
return;
splay(findnxt(root,v),root);
root=son[x][1];
son[root][0]=son[x][0];
fa[son[x][0]]=root;
fa[root]=son[x][0]=son[x][1]=0;
pushup(root);
}
int Rank(int v){
splay(find(root,v),0);
return tot[son[root][0]]+1;
}
int main(){
val[1]=2147483647;
cnt[1]=tot[1]=1;
scanf("%d",&n);
while (n--){
int opt,x;
scanf("%d%d",&opt,&x);
if (opt==1) Insert(x);
if (opt==2) Delete(x);
if (opt==3) printf("%d\n",Rank(x));
if (opt==4) printf("%d\n",val[findkth(root,x)]);
if (opt==5) printf("%d\n",val[findpre(root,x)]);
if (opt==6) printf("%d\n",val[findnxt(root,x)]);
}
return 0;
}
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
const int N=100005;
struct Splay{
int fa[N],lc[N],rc[N],size[N],cnt[N],val[N],root,tot;
void clear(){//splay³õʼ»¯
root=tot=0,memset(size,0,sizeof size),memset(cnt,0,sizeof cnt);
}
void update(int x){//¼ÆËã(¸üÐÂ)ijһ¸ö½ÚµãµÄsize
if (x){
size[x]=cnt[x];
size[x]+=lc[x]?size[lc[x]]:0;
size[x]+=rc[x]?size[rc[x]]:0;
}
}
void zig(int x){//ÓÒÐý
if (!fa[x])
return;
int y=fa[x],z=fa[y];
if (z)
if (lc[z]==y)
lc[z]=x;
else
rc[z]=x;
fa[x]=z;
fa[y]=x;
fa[rc[x]]=y;
lc[y]=rc[x];
rc[x]=y;
update(y);
update(x);
}
void zag(int x){//×óÐý
if (!fa[x])
return;
int y=fa[x],z=fa[y];
if (z)
if (lc[z]==y)
lc[z]=x;
else
rc[z]=x;
fa[x]=z;
fa[y]=x;
fa[lc[x]]=y;
rc[y]=lc[x];
lc[x]=y;
update(y);
update(x);
}
void splay(int rt,int x){//splayÖ÷¹ý³Ì(ÔÚÒÔrtΪ¸ùµÄ×ÓÊ÷ÖÐsplay£¬×îÖÕx³ÉΪµ±Ç°×ÓÊ÷µÄÐÂ׿×Ú)
rt=fa[rt];
int y,z;
while (fa[x]!=rt){
y=fa[x];
z=fa[y];
if (z&&z!=rt){
if (lc[z]==y&&lc[y]==x)
zig(y),zig(x);
else if (lc[z]==y&&rc[y]==x)
zag(x),zig(x);
else if (rc[z]==y&&lc[y]==x)
zig(x),zag(x);
else
zag(y),zag(x);
}
else if (lc[y]==x)
zig(x);
else
zag(x);
}
if (!fa[x])
root=x;
}
void splay(int x){
splay(root,x);
}
void ins(int &k,int key,int p){//ÔÚkÕâ¸ö×ÓÊ÷ÖвåÈëֵΪkeyµÄÊý£¬µ±Ç°½ÚµãµÄ¸¸Ç×Ϊp
if (!k){
size[k=++tot]=cnt[k]=1;
lc[k]=rc[k]=0;
val[k]=key;
fa[k]=p;
splay(k);
return;
}
size[k]++;
if (key==val[k]){
cnt[k]++;
return;
}
if (key<val[k])
ins(lc[k],key,k);
else
ins(rc[k],key,k);
}
void ins(int key){//ÔÚÕû¸ösplayÀïÃæ²åÈëָΪkeyµÄÊý
if (!root){
size[root=++tot]=cnt[root]=1;
lc[root]=rc[root]=0;
val[root]=key;
fa[root]=0;
return;
}
ins(root,key,0);
}
int find(int k,int key){//ÔÚÒÔkΪ¸ùµÄsplayÀïÃæ²éÕÒֵΪkeyµÄÊýµÄ´æ´¢±àºÅ
int tmp=k;
while (k)
if (val[k]==key)
break;
else
k=key<val[k]?lc[k]:rc[k];
if (k)
splay(k);
return k;
}
int find(int key){//splayÀïÃæ²éÕÒֵΪkeyµÄÊýµÄ´æ´¢±àºÅ
return find(root,key);
}
void del(int key){//ɾ³ýֵΪkeyµÄÊý£¨µ«ÊÇtot²»¼õ£¬Òâζ×ÅÓÐ1¸ö¿Õ¼ä»áÀË·Ñ£©
int x=find(key),ls=lc[x],rs=rc[x];
if (!x)
return;
if (--cnt[x])
return;
if (!ls&&!rs){
clear();
return;
}
if (!ls)
root=rs,fa[rs]=0;
else if (!rs)
root=ls,fa[ls]=0;
else {
int lson=getmax(ls);
swap(lson,ls);
fa[lson]=0;
splay(ls);
rc[ls]=rs;
fa[rs]=ls;
update(ls);
}
}
int getmin(int k){//ÔÚ¸ùΪkµÄsplayÖÐÕÒ×îСֵµÄ´æ´¢±àºÅ
return lc[k]?getmin(lc[k]):k;
}
int getmax(int k){//ÔÚ¸ùΪkµÄsplayÖÐÕÒ×î´óÖµµÄ´æ´¢±àºÅ
return rc[k]?getmax(rc[k]):k;
}
int findkth(int k){//ѰÕÒµÚkСµÄ
int t=root;
while (t){
if (size[lc[t]]<k&&k<=size[lc[t]]+cnt[t])
break;
if (k<=size[lc[t]])
t=lc[t];
else
k-=size[lc[t]]+cnt[t],t=rc[t];
}
splay(t);
return t;
}
int findpre(int k,int key){//ÔÚ¸ùΪkµÄsplayÖÐÕÒkeyµÄǰÇý£¨¼´Öµ<keyµÄ×î´óÖµ£©µÄ´æ´¢±àºÅ
if (!k)
return 0;
if (key<=val[k])
return findpre(lc[k],key);
else {
int tmp=findpre(rc[k],key);
return tmp?tmp:k;
}
}
int findpre(int key){return findpre(root,key);}//ÕÒkeyµÄǰÇý£¨¼´Öµ<keyµÄ×î´óÖµ£©µÄ´æ´¢±àºÅ
int findnxt(int k,int key){//ÔÚ¸ùΪkµÄsplayÖÐÕÒkeyµÄºó¼Ì£¨¼´Öµ>keyµÄ×îСֵ£©µÄ´æ´¢±àºÅ
if (!k)
return 0;
if (key>=val[k])
return findnxt(rc[k],key);
else {
int tmp=findnxt(lc[k],key);
return tmp?tmp:k;
}
}
int findnxt(int key){return findnxt(root,key);}//ÕÒkeyµÄºó¼Ì£¨¼´Öµ>keyµÄ×îСֵ£©µÄ´æ´¢±àºÅ
}s;
int n,opt,x;
int main(){
scanf("%d",&n);
s.clear();
for (int i=1;i<=n;i++){
scanf("%d%d",&opt,&x);
if (opt==1) s.ins(x);
if (opt==2) s.del(x);
if (opt==3){//ÇóֵΪxµÄÃû´Î
s.splay(s.find(x));
printf("%d\n",s.size[s.lc[s.root]]+1);
}
if (opt==4) printf("%d\n",s.val[s.findkth(x)]);
if (opt==5) printf("%d\n",s.val[s.findpre(x)]);
if (opt==6) printf("%d\n",s.val[s.findnxt(x)]);
}
return 0;
}