1 /**************************************************** 2 题目: Black Box(poj 1442) 3 链接: http://poj.org/problem?id=1442 4 题意: 给n个数,m个询问,对第i数个询问前Xi个数中第 5 i小的是那个数。 6 算法: treap树 7 *****************************************************/ 8 #include<iostream> 9 #include<algorithm> 10 #include<cstdio> 11 #include<cstring> 12 #include<cstdlib> 13 using namespace std; 14 15 typedef struct Node 16 { 17 Node *l,*r; 18 int val,pri; ///val当前节点的值,pri当前节点的优先级 19 int sz; ///子树的节点数 20 Node(int x) ///构造函数初始化 21 { 22 l=r=NULL; 23 pri=rand(); 24 val=x; 25 sz=1; 26 } 27 }Node; 28 Node *root; ///根节点 29 30 int getsz(Node *T) ///求子树的节点数 31 { 32 if (T==NULL) return 0; 33 return T->sz; 34 } 35 36 Node *L_rotate(Node *T) ///右节点的优先级大于当前节点,进行左旋转 37 { 38 Node *A=T->r; 39 T->r=A->l; 40 A->l=T; 41 A->sz=T->sz; 42 T->sz=getsz(T->l)+getsz(T->r)+1; ///T->l可能为空,要用getsz函数 43 return A; 44 } 45 Node *R_rotate(Node *T) ///左节点的优先级大于当前节点,进行右旋转 46 { 47 Node *A=T->l; 48 T->l=A->r; 49 A->r=T; 50 A->sz=T->sz; 51 T->sz=getsz(T->l)+getsz(T->r)+1; 52 return A; 53 } 54 void inser(Node *&T,int val) ///插入函数,和二叉排序树差不多,多了个优先级的改变 55 { 56 if (T==NULL) 57 { 58 T=new Node(val); 59 return ; 60 } 61 T->sz++; 62 if (T->val>=val) 63 { 64 inser(T->l,val); 65 if ((T->l->pri)<(T->pri)) T=R_rotate(T); ///判断优先级并旋转 66 } 67 else 68 { 69 inser(T->r,val); 70 if ((T->r->sz)<(T->pri)) T=L_rotate(T); 71 } 72 } 73 int Find(Node *T,int k) ///查找函数 74 { 75 int temp=getsz(T->l)+1; 76 if (temp==k) return T->val; 77 if (temp>k) return Find(T->l,k); 78 return Find(T->r,k-temp); 79 } 80 81 int a[100005]; 82 83 int main() 84 { 85 int n,m; 86 root=NULL; 87 scanf("%d%d",&n,&m); 88 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 89 int j=1; 90 for (int i=1;i<=m;i++) 91 { 92 int x; 93 scanf("%d",&x); 94 for (;j<=x;j++) inser(root,a[j]); 95 printf("%d\n",Find(root,i)); 96 } 97 }