BZOJ 3224: Tyvj 1728 普通平衡树
Fancy
posted @ 2015年7月05日 17:23
in BZOJ
, 449 阅读
题目大意:您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
就是个splay 没了
也可以用STL库写
#include<cstdio> #define N 200005 using namespace std; int son[N][3],num[N][3],f[N],a[N]; int opt,n,i,root,x,node,ans,flag; inline void Rotate(int x,int w) { int y=f[x],z=f[y]; son[y][3-w]=son[x][w]; if (son[x][w]) f[son[x][w]]=y; f[x]=z; num[y][3-w]=num[x][w]; num[x][w]+=num[y][w]+1; if (z) { if (y==son[z][1]) son[z][1]=x; else son[z][2]=x; } f[y]=x;son[x][w]=y; } inline void splay(int x) { int y; while (f[x]) { y=f[x]; if (!f[y]) { if (x==son[y][1]) Rotate(x,2);else Rotate(x,1); continue; } if (y==son[f[y]][1]) { if (x==son[y][1]) Rotate(y,2),Rotate(x,2); else Rotate(x,1),Rotate(x,2); } else { if (x==son[y][2]) Rotate(y,1),Rotate(x,1); else Rotate(x,2),Rotate(x,1); } } root=x; } inline void insert(int x,int add) { if (add<=a[x]) { if (!son[x][1]) son[x][1]=++node,a[node]=add,f[node]=x; else insert(son[x][1],add); num[x][1]++; } else { if (!son[x][2]) son[x][2]=++node,a[node]=add,f[node]=x; else insert(son[x][2],add); num[x][2]++; } } inline void del(int x,int add) { if (!x) return; if (add==a[x]) { splay(x); if (!son[x][1]&&!son[x][2]){root=0;return;} if (!son[x][1]) {root=son[x][2];f[son[x][2]]=0;return;} if (!son[x][2]) {root=son[x][1];f[son[x][1]]=0;return;} int find=son[x][1],temp=son[x][2]; while (son[find][2]) find=son[find][2]; splay(find);son[find][2]=temp;f[temp]=find; return; } if (add<a[x]) del(son[x][1],add);else del(son[x][2],add); } inline int Kth(int x,int add,int now) { insert(root,add);splay(node); int ans=num[node][1]+1; del(node,add); return ans; } inline int Ask(int x,int k) { if (k==num[x][1]+1) return a[x]; if (k<=num[x][1]) return Ask(son[x][1],k); return Ask(son[x][2],k-num[x][1]-1); } inline int pred(int x,int k) { int find=son[x][1];if (!find) return 0; while (son[find][2]) find=son[find][2]; if (a[find]!=k) flag=1;return find; } inline int succ(int x,int k) { int find=son[x][2];if (!find) return 0; while (son[find][1]) find=son[find][1]; if (a[find]!=k) flag=1;return find; } int main() { scanf("%d",&n);root=0; for (i=1;i<=n;i++) { scanf("%d%d",&opt,&x); if (opt==1) insert(root,x),splay(node); if (opt==2) del(root,x); if (opt==3) printf("%d\n",Kth(root,x,0)); if (opt==4) printf("%d\n",Ask(root,x)); if (opt==5) { insert(root,x);splay(node); for (flag=0,ans=pred(root,x);!flag||!ans;splay(ans),ans=pred(root,x)); del(root,x);printf("%d\n",a[ans]); } if (opt==6) { insert(root,x);splay(node); for (flag=0,ans=succ(root,x);!flag||!ans;splay(ans),ans=succ(root,x)); del(root,x);printf("%d\n",a[ans]); } } return 0; }
STL:
#include<cstdio> #include<vector> #include<algorithm> using namespace std; const int INF=10000000; int n; vector<int> tree; int find(int x) { return lower_bound(tree.begin(),tree.end(),x)-tree.begin()+1; } int main() { scanf("%d",&n); tree.reserve(200005); int opt,x; for(int i=1;i<=n;i++) { scanf("%d%d",&opt,&x); switch(opt) { case 1:tree.insert(upper_bound(tree.begin(),tree.end(),x),x);break; case 2:tree.erase(lower_bound(tree.begin(),tree.end(),x));break; case 3:printf("%d\n",find(x));break; case 4:printf("%d\n",tree[x-1]);break; case 5:printf("%d\n",*--lower_bound(tree.begin(),tree.end(),x));break; case 6:printf("%d\n",*upper_bound(tree.begin(),tree.end(),x));break; } } return 0; }