BZOJ3224: Tyvj 1728 普通平衡树
题解:权值平衡树 按题意模拟即可
#include <bits/stdc++.h> #define rt ch[ch[root][1]][0] const int MAXN=1e5+10; const int inf=1e9+10; using namespace std; int ch[MAXN][2],root,pre[MAXN],size[MAXN],key[MAXN],cnt,maxn[MAXN]; void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;maxn[x]=max(max(maxn[ch[x][0]],maxn[ch[x][1]]),key[x]);} void Treavel(int x) { if(x) { // cout<<x<<endl; Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treavel(ch[x][1]); } } void debug(int rp) { printf("root:%d\n",rp); Treavel(rp); } void newnode(int &x,int fa,int vul){ x=++cnt;ch[x][0]=ch[x][1]=0;pre[x]=fa;size[x]=1;maxn[x]=key[x]=vul; } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y); } void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x); else{ int y=pre[x];int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind); else rotate(y,kind),rotate(x,kind); } } if(goal==0) root=x; up(x); } int minn; int find1(int x,int vul){ //if(!x) return ; if(key[x]==vul){ if(maxn[ch[x][0]]==vul) return find1(ch[x][0],vul); else return x; } else if(key[x]<vul) return find1(ch[x][1],vul); else return find1(ch[x][0],vul); } int find2(int x,int siz){ if(siz==size[ch[x][0]]+1) return x; else if(siz<=size[ch[x][0]]) return find2(ch[x][0],siz); else return find2(ch[x][1],siz-size[ch[x][0]]-1); } //操作 void insert(int &x,int vul,int fa){ if(x==0){newnode(x,fa,vul);return ;} if(key[x]>vul) insert(ch[x][0],vul,x); else insert(ch[x][1],vul,x); up(x); } void erase(int vul){ splay(find1(root,vul),0);int t=size[ch[root][0]]+1; splay(find2(root,t-1),0);splay(find2(root,t+1),root); pre[rt]=0;rt=0;up(ch[root][1]);up(root); } void rank1(int vul){ splay(find1(root,vul),0); printf("%d\n",size[ch[root][0]]); } void frank(int x){ printf("%d\n",key[find2(root,x+1)]); } int ans; void vul_pre(int x,int vul){ if(!x) return ; if(key[x]>=vul) vul_pre(ch[x][0],vul); else{ int t=vul-key[x]; if(t<=vul-ans) ans=key[x],vul_pre(ch[x][1],vul); else vul_pre(ch[x][1],vul); } } void vul_last(int x,int vul){ if(!x) return ; if(key[x]<=vul) vul_last(ch[x][1],vul); else{ int t=key[x]-vul; if(t<=ans-vul) ans=key[x],vul_last(ch[x][0],vul); else vul_last(ch[x][0],vul); } } void inte(){ cnt=0; newnode(root,0,-1*inf); newnode(ch[root][1],root,inf); } int main(){ //freopen("1.in","r",stdin); //freopen("3.out","w",stdout); int n;scanf("%d",&n); int op,vul; inte(); for(int i=1;i<=n;i++){ scanf("%d%d",&op,&vul); if(op==1) insert(root,vul,0); else if(op==2) erase(vul); else if(op==3) rank1(vul); else if(op==4) frank(vul); else if(op==5){ ans=-1*inf;vul_pre(root,vul); printf("%d\n",ans); } else{ ans=inf;vul_last(root,vul); printf("%d\n",ans); } } return 0; }
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 21834 Solved: 9749
[Submit][Status][Discuss]
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]