Treap的入门题目,每个结点多维护一个size表示以它为根的子树的结点数,然后查kth的时候一层一层向下即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <ctime> 6 using namespace std; 7 8 struct Node 9 { 10 Node * ch[2]; 11 int r; 12 int v; 13 int s; 14 int cmp( int x ) 15 { 16 if ( x == v ) return -1; 17 return x < v ? 0 : 1; 18 } 19 void maintain() 20 { 21 s = 1; 22 if ( ch[0] != NULL ) s += ch[0]->s; 23 if ( ch[1] != NULL ) s += ch[1]->s; 24 } 25 }; 26 27 void rotate( Node * & o, int d ) 28 { 29 Node * k = o->ch[d ^ 1]; 30 o->ch[d ^ 1] = k->ch[d]; 31 k->ch[d] = o; 32 o->maintain(); 33 k->maintain(); 34 o = k; 35 } 36 37 void insert( Node * & o, int x ) 38 { 39 if ( o == NULL ) 40 { 41 o = new Node(); 42 o->ch[0] = o->ch[1] = NULL; 43 o->v = x; 44 o->r = rand(); 45 o->s = 1; 46 } 47 else 48 { 49 int d = ( x < o->v ? 0 : 1 ); 50 insert( o->ch[d], x ); 51 if ( o->ch[d]->r > o->r ) 52 { 53 rotate( o, d ^ 1 ); 54 } 55 o->maintain(); 56 } 57 } 58 59 int kth( Node * o, int k ) 60 { 61 int tmp = ( o->ch[0] == NULL ? 0 : o->ch[0]->s ); 62 if ( k == tmp + 1 ) return o->v; 63 else if ( k < tmp + 1 ) return kth( o->ch[0], k ); 64 else return kth( o->ch[1], k - tmp - 1 ); 65 } 66 67 const int N = 30001; 68 int a[N]; 69 70 int main () 71 { 72 int n, m; 73 while ( scanf("%d%d", &n, &m) != EOF ) 74 { 75 Node * root = NULL; 76 for ( int i = 1; i <= n; i++ ) 77 { 78 scanf("%d", a + i); 79 } 80 int tt, cnt = 1; 81 for ( int i = 1; i <= m; i++ ) 82 { 83 scanf("%d", &tt); 84 while ( cnt <= tt ) 85 { 86 insert( root, a[cnt++] ); 87 } 88 printf("%d ", kth( root, i )); 89 } 90 } 91 return 0; 92 }