您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Splay入门题。。。断断续续写了几天。。。。
自己写的常数好大。。。。。
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
对于操作3,4,5,6每行输出一个数,表示对应答案
平衡树
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <algorithm> using namespace std; #define Key_value (ch[ch[root][1]][0]) const int maxn=110100; const int INF=0x3f3f3f3f; int pre[maxn],ch[maxn][2],key[maxn],s[maxn]; int root,tot1; map<int,int> nct; /************debug*********************/ void showit(int x) { if(x) { showit(ch[x][0]); cout<<"节点:"<<x<<" key:"<<key[x]<<" S值:"<<s[x]<<" 左孩子:"<<ch[x][0]<<" 右孩子:"<<ch[x][1]<<" 父节点:"<<pre[x]<<endl; showit(ch[x][1]); } } /************debug*********************/ void NewNode(int &r,int father,int k) { r=++tot1; key[r]=k; pre[r]=father; ch[r][0]=ch[r][1]=0; s[r]=1; nct[k]=1; } void push_up(int x) { if(!x) return ; s[x]=nct[key[x]]+s[ch[x][1]]+s[ch[x][0]]; } void init() { root=tot1=0; ch[root][0]=ch[root][1]=pre[root]=s[root]=key[root]=0; nct.clear(); } void Rotate(int x,int kind) { int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; pre[x]=pre[y]; if(pre[x]) ch[pre[y]][ch[pre[y]][1]==y]=x; ch[x][kind]=y; pre[y]=x; push_up(y); } void Splay(int r,int goal) { while(pre[r]!=goal) { if(pre[pre[r]]==goal) { Rotate(r,ch[pre[r]][0]==r); } else { int y=pre[r]; int kind=(ch[pre[y]][0]==y); if(ch[y][kind]==r) Rotate(r,!kind); else Rotate(y,kind); Rotate(r,kind); } } push_up(r); if(goal==0) root=r; } void Insert(int x) { int r=root; if(r==0) {NewNode(root,0,x); return ;} while(ch[r][key[r]<=x]) { if(key[r]==x) break; r=ch[r][key[r]<=x]; } if(key[r]==x) { nct[x]++; Splay(r,0); } else { NewNode(ch[r][key[r]<=x],r,x); Splay(ch[r][key[r]<=x],0); } push_up(r); } int Find_Max(int r) { while(ch[r][1]) r=ch[r][1]; return r; } int Find_Min(int r) { while(ch[r][0]) r=ch[r][0]; return r; } void Erase(int x) { int r=root; while(ch[r][key[r]<=x]) { if(key[r]==x) break; r=ch[r][key[r]<=x]; } nct[x]--; if(nct[x]>0) { Splay(r,0); push_up(r); } else if(nct[x]<=0) { Splay(r,0); nct.erase(x); int rt=Find_Max(ch[root][0]); if(rt) { Splay(rt,root); pre[rt]=pre[root]; ch[0][ch[0][1]==root]=rt; pre[ch[root][1]]=rt; ch[rt][1]=ch[root][1]; root=rt; } else { if(ch[root][1]) { pre[ch[root][1]]=0; ch[0][ch[0][1]==root]=ch[root][1]; root=ch[root][1]; } else init(); } push_up(root); } } int get_rank(int x) { int r=root,temp=0; while(ch[r][key[r]<=x]) { if(key[r]==x) break; if(key[r]<=x) temp+=s[r]-s[ch[r][1]]; r=ch[r][key[r]<=x]; } return s[ch[r][0]]+1+temp; } int get_pre(int x) { int ret=-INF; int r=root; while(r) { if(key[r]<x) { ret=max(ret,key[r]); r=ch[r][1]; } else r=ch[r][0]; } return ret; } int get_nxt(int x) { int ret=INF; int r=root; while(r) { if(key[r]>x) { ret=min(ret,key[r]); r=ch[r][0]; } else r=ch[r][1]; } return ret; } int get_kth(int x) { int r=root; while(true) { int left=s[ch[r][0]],right=s[ch[r][0]]+nct[key[r]]+1; if(x>left&&x<right) { Splay(r,0); return key[r]; } else if(x<=left) { r=ch[r][0]; } else if(x>=right) { r=ch[r][1]; x-=right-1; } } } int main() { int T_T; while(scanf("%d",&T_T)!=EOF) { init(); int a,b; for(int i=0;i<T_T;i++) { scanf("%d%d",&a,&b); if(a==1) Insert(b); else if(a==2) Erase(b); else if(a==3) printf("%d\n",get_rank(b)); else if(a==4) printf("%d\n",get_kth(b)); else if(a==5) printf("%d\n",get_pre(b)); else if(a==6) printf("%d\n",get_nxt(b)); } } return 0; }