POJ 1442 Black Box(Treap)
http://poj.org/problem?id=1442
题意:
有一个数据结构支持两种操作A与Get操作,其中A x表示插入x. Get i表示返回结构中的第i小的数.给你A和Get操作的顺序和参数,现在要你对每个Get输出值.
分析:
其实就是名次树的简单应用而已.且原题中还保证了每个Get都能获得合法的数.
POJ好多BUG啊,代码第48行,如果我用我自己写的operator<直接比较o->ch[d] 和o的大小就无限超时,找了半天BUG.
AC代码:
#include<cstdlib> #include<cstring> #include<cstdio> #include<ctime> using namespace std; struct Node { Node *ch[2]; int r,v,s; Node(int v):v(v) { s=1; ch[0]=ch[1]=NULL; r=rand(); } bool operator<(const Node &b)const { return r<b.r; } int cmp(int x) { if(x==v)return -1; return x<v?0:1; } void maintain() { s=1; if(ch[0] != NULL) s+=ch[0]->s; if(ch[1] != NULL) s+=ch[1]->s; } }; void rotate(Node* &o,int d) { Node *k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(); k->maintain(); o=k; } void insert(Node* &o,int x)//可以插入v值相同的值 { if(o==NULL) o=new Node(x); else { int d= (x< (o->v))? 0:1; insert(o->ch[d],x); if(o->ch[d]->r>o->r)//这里用o->ch[d] > o的话 无限超时*************************** rotate(o,d^1); } o->maintain(); } int kth(Node *o,int k)//返回第k小的值 { //if(o==NULL || k<=0 || k>o->s) return 0; int s = (o->ch[0]==NULL)? 0:o->ch[0]->s; if(k==s+1) return o->v; else if(k<=s) return kth(o->ch[0],k); else return kth(o->ch[1],k-s-1); } const int maxn=30000+10; int m,n; int a[maxn],g; int main() { srand(100); Node *root=NULL;//注意这里 scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) scanf("%d",&a[i]); int j=1; for(int i=1;i<=n;i++) { scanf("%d",&g); for( ;j<=g;j++) insert(root,a[j]); printf("%d\n",kth(root,i));// } return 0; }