平衡树模板题。由于有重复的数嘛,就加以个s[ ]记录一下这个数有几个,那么在删除加入的时候就会有一些小细节处理。由于这道题要找前驱和后继,而且查找数是按照值的大小查找,原来的 find 操作就要改一下,类似与树上权值二分,开一个全局变量,若我当前点的值大于等于查找值,记录下来,此点值大于我,则向左走,小于我向右走,这样找到的就是刚好大于等于查找值的点。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define N 150005 #define inf 0x7fffffff/2 using namespace std; int n,cnt=2,c[N][2],fa[N],root; int sum[N],s[N],val[N]; void pushup(int x){ int l=c[x][0],r=c[x][1]; sum[x]=sum[l]+sum[r]+s[x]; } void rot(int x,int &f){ int y=fa[x],z=fa[y]; int l=(c[y][0]!=x),r=l^1; if(y==f)f=x; else {if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;} fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; pushup(y);pushup(x); } void splay(int x,int &f){ while(x!=f){ int y=fa[x],z=fa[y]; if(y!=f){if(c[z][0]==y^c[y][0]==x)rot(x,f);else rot(y,f);} rot(x,f); } } int build(int l,int r){ int mid=(l+r)/2; if(l>r)return 0; c[mid][0]=build(l,mid-1); if(c[mid][0])fa[c[mid][0]]=mid; c[mid][1]=build(mid+1,r); if(c[mid][1])fa[c[mid][1]]=mid; pushup(mid); return mid; } int geth(int x){ if(!c[x][1])return x; else return geth(c[x][1]); } int getq(int x){ if(!c[x][0])return x; else return getq(c[x][0]); } int po; void get(int root,int x){//找到第一个大于等于我的点 if(val[root]>=x)po=root; if(val[root]==x)return; int l=c[root][0],r=c[root][1]; if(val[root]<x&&r)get(r,x); if(val[root]>x&&l)get(l,x); } int getit(int x,int v){ if(sum[c[x][0]]<v&&sum[c[x][0]]+s[x]>=v)return x; else if(sum[c[x][0]]>=v)return getit(c[x][0],v); else return getit(c[x][1],v-sum[c[x][0]]-s[x]); } int main(){ // freopen("","r",stdin); // freopen("","w",stdout); int i,j,k,op,x,y,z,u1,u2,u3,u4; scanf("%d",&n); val[1]=-inf; val[2]=inf; root=build(1,2); for(i=1;i<=n;i++){ scanf("%d",&op); if(op==1){ scanf("%d",&x); get(root,x); u1=po; splay(u1,root); if(val[u1]==x){ s[u1]++; sum[u1]++; } else { u2=geth(c[root][0]); splay(u2,c[root][0]); cnt++; val[cnt]=x;s[cnt]=1;sum[cnt]=1; fa[cnt]=u2; c[u2][1]=cnt; pushup(u2); pushup(u1); } } if(op==2){ scanf("%d",&x); get(root,x); u1=po; splay(u1,root); if(s[u1]>1)s[u1]--; else { u2=geth(c[u1][0]); u3=getq(c[u1][1]); splay(u2,root); splay(u3,c[root][1]); fa[c[u3][0]]=0; sum[c[u3][0]]=0; s[c[u3][0]]=0;val[c[u3][0]]=0; c[u3][0]=0; pushup(u3); pushup(u2); } } if(op==3){ scanf("%d",&x); get(root,x); u1=po; splay(u1,root); printf("%d\n",sum[c[root][0]]+1); } if(op==4){//uu++; scanf("%d",&x); u1=getit(root,x); printf("%d\n",val[u1]); } if(op==5){//uu++; scanf("%d",&x); get(root,x); u1=po; splay(u1,root); u2=geth(c[root][0]); printf("%d\n",val[u2]); } if(op==6){ scanf("%d",&x); get(root,x); u1=po; if(val[u1]==x){ splay(u1,root); u1=getq(c[u1][1]); } printf("%d\n",val[u1]); } } // fclose(stdin); // fclose(stdout); return 0; }(为什么我经常翻po这个变量的牌子??zro POPOQQQ orz)