Description
有一个序列含有一定数量的元素,现在要求写一个程序,满足以下几个要求: 【A】支持插入操作(这个序列不允许有重复元素,即是说,如果待插入的元素已经出现在这个序列中,那么请忽略此操作) 【B】支持删除操作(如果此序列中不包含待删除的这个元素,则忽略此操作,否则删除这个元素) 【C】查找元素x的前继元素(前继元素是指:小于x且与x最接近的元素,当然,如果x已经是序列中的最小元素,则x没有前继元素) 【D】查找元素x的后继元素(后继元素是指:大于x且与x最接近的元素,当然,如果x已经是序列中的最大元素,则x没有后继元素) 【E】找第K小的元素 【F】求某个元素x的秩(即x的排名是多少,从小到大排序)
Input
多组数据(整个文件以输入 -1 结束) 对于每组数据,有若干行(最多100000行),表示的意义如下: 【A】 insert x 【B】 delete x 【C】 predecessor x 【D】 successor x 【E】 Kth x 【F】 rank x 这6种操作的意义与上面的定义相对应! 【G】 print 表示从小到大输出序列中的所有元素 【H】 end 表示结束本组数据 每组输入数据后有一空行!
Output
对于以上8种操作,分别输出对应信息,如下: 【A】 insert x 不用输出任何信息 【B】 delete x 如果x存在,则删除x,否则输出 Input Error 【C】 predecessor x 如果x不存在,输出 Input Error;否则如果x是序列中的最小元素,输出对应信息(见样例),否则输出x的前继元素 【D】 successor x 如果x不存在,输出 Input Error;否则如果x是序列中的最大元素,输出对应信息(见样例),否则输出x的后继元素 【E】 Kth x 如果x不合法,输出 Input Error;否则输出第Kth小的元素(见样例) 【F】 rank x 如果x不存在,输出 Input Error;否则输出x的排名(见样例) 【G】 print 从小到大输出序列中的所有元素,每个元素后加一个逗号,并在最后加上 end of print(见样例) 【H】 end 输出 end of this test
insert 20 insert 5 insert 1 insert 15 insert 9 insert 25 insert 23 insert 30 insert 35 print Kth 0 Kth 1 Kth 3 Kth 5 Kth 7 Kth 9 Kth 10 rank 1 rank 3 rank 5 rank 15 rank 20 rank 30 rank 31 rank 35 successor 15 successor 35 successor 25 successor 26 predecessor 1 predecessor 20 predecessor 23 predecessor 15 predecessor 111 delete 9 delete 15 delete 25 delete 23 delete 20 print Kth 3 Kth 4 rank 30 rank 35 end -1
1,5,9,15,20,23,25,30,35,end of print Input Error The 1_th element is 1 The 3_th element is 9 The 5_th element is 20 The 7_th element is 25 The 9_th element is 35 Input Error The rank of 1 is 1_th Input Error The rank of 5 is 2_th The rank of 15 is 4_th The rank of 20 is 5_th The rank of 30 is 8_th Input Error The rank of 35 is 9_th The successor of 15 is 20 35 is the maximum The successor of 25 is 30 Input Error 1 is the minimum The predecessor of 20 is 15 The predecessor of 23 is 20 The predecessor of 15 is 9 Input Error 1,5,30,35,end of print The 3_th element is 30 The 4_th element is 35 The rank of 30 is 3_th The rank of 35 is 4_th end of this test
#include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<algorithm> #include<math.h> #include<vector> #include<map> #include<string> using namespace std; #define nn 200005 #define inf 0x7ffff struct treap { int sz,key,fix,num; treap *ch[2]; treap(int key) { sz=1; num=1; fix=rand(); this->key=key; ch[0]=ch[1]=0; } int compare(int x) const { if(x==key) return -1; return x<key?0:1; } void maintain() { sz=num; if(ch[0]!=0) sz+=ch[0]->sz; if(ch[1]!=0) sz+=ch[1]->sz; } }; treap* root; void rotate(treap* &t,int d)//旋转 { treap *k=t->ch[d^1]; t->ch[d^1]=k->ch[d]; k->ch[d]=t; t->maintain(); k->maintain(); t=k; } void insert(treap* &t,int x)//添加 { if(t==0) t=new treap(x); else { int d=x<t->key?0:1; insert(t->ch[d],x); if(t->ch[d]->fix>t->fix) rotate(t,d^1); } t->maintain(); } void Delete(treap* &t,int x)//删除 { int d=t->compare(x); if(d==-1) { treap *tmp=t; if(t->ch[0]==0) { t=t->ch[1]; delete tmp; tmp=0; } else if(t->ch[1]==0) { t=t->ch[0]; delete tmp; tmp=0; } else { int k=t->ch[0]->fix>t->ch[1]->fix?1:0; rotate(t,k); Delete(t->ch[k],x); } } else Delete(t->ch[d],x); if(t!=0) t->maintain(); } bool Find(treap *t,int x)//查找 { while(t!=0) { int d=t->compare(x); if(d==-1) return true; t=t->ch[d]; } return false; } int kth(treap *t,int k)//找第K小的元素 { if(t==0||k<=0||k>t->sz) return -1; if(t->ch[0]==0&&k==1) return t->key; if(t->ch[0]==0) return kth(t->ch[1],k-1); if(t->ch[0]->sz>=k) return kth(t->ch[0],k); if(t->ch[0]->sz+1==k) return t->key; return kth(t->ch[1],k-1-t->ch[0]->sz); } int Rank(int x) //x的排名是多少,从小到大排序 { int ans=0; treap* p=root; while(1) { if(p->key==x) { ans+=1+(p->ch[0]?p->ch[0]->sz:0); break; } else if(x<p->key) p=p->ch[0]; else { ans+=p->num+(p->ch[0]?p->ch[0]->sz:0); p=p->ch[1]; } } return ans; } int depth(treap *t) { if(t==0) return -1; int l=depth(t->ch[0]); int r=depth(t->ch[1]); return l<r?(r+1):(l+1); } void delettreap(treap* &t)//释放空间 { if(t==0) return; if(t->ch[0]!=0) delettreap(t->ch[0]); if(t->ch[1]!=0) delettreap(t->ch[1]); delete t; t=0; } void Print(treap *t)//打印树,从小到大 { if(t==0) return; Print(t->ch[0]); printf("%d,",t->key); Print(t->ch[1]); } int pre(int x) { treap* p=root; int ans=0; bool fuck=0; while(p) { if(p->key<x) { ans=p->key; fuck=1; } p=p->ch[p->key<x]; } if(fuck) return ans; return inf; } int suc(int x) { treap* p=root; int ans=0; bool fuck=0; while(p) { if(p->key>x) { ans=p->key; fuck=1; } p=p->ch[p->key<=x]; } if(fuck) return ans; return inf; } int main() { int n,m; char op[30]; while(~scanf("%s",op)) { if(strcmp(op,"-1")==0) break; if(op[0]=='e') { puts("end of this test"); delettreap(root); continue; } if(op[0]=='p'&&op[2]=='i') { Print(root); puts("end of print"); } else { int x; scanf("%d",&x); if(op[0]=='i') { if(!Find(root,x)) insert(root,x); } else if(op[0]=='d') { if(Find(root,x)) Delete(root,x); else printf("Input Error\n"); } else if(op[0]=='p'&&op[2]=='e') { if(Find(root,x)) { int y=pre(x); if(y<inf) printf("The predecessor of %d is %d\n",x,y); else printf("%d is the minimum\n",x); } else printf("Input Error\n"); } else if(op[0]=='s') { if(Find(root,x)) { int y=suc(x); if(y<inf) printf("The successor of %d is %d\n",x,y); else printf("%d is the maximum\n",x); } else printf("Input Error\n"); } else if(op[0]=='K') { int y=kth(root,x); if(y==-1) printf("Input Error\n"); else printf("The %d_th element is %d\n",x,y); } else if(op[0]=='r') { if(!Find(root,x)) printf("Input Error\n"); else printf("The rank of %d is %d_th\n",x,Rank(x)); } } } return 0; }