两种操作, add:是向序列中加入一个数 , get是问第k小数是谁 , 可以用优先队列 , 也可以用treap , 还可以用线段树 。
线段树的做法为 , 先离散化 , 然后每次都往线段树中加入数 , 线段树相应的的点+1 , 然后可以二分找 。 思想很明显, 代码实现注意细节就行 , 不过我没去写了。这里只给出2种解法。
1:优先队列:两个优先队列, 一个最小优先 , 一个最大优先, 最大优先保存前i-1小的数 , 最小优先里面的数都比最大优先的大 ,那么每次询问第i小的数时 , 最小优先队列的第一个就是答案。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<algorithm> 6 7 const int N = 33333 ; 8 9 using namespace std ; 10 11 priority_queue<int , vector<int> , greater<int> >Min_Q ; 12 priority_queue<int , vector<int> , less<int> >Max_Q ; 13 14 int val[N] , n , m ; 15 16 int main() 17 { 18 while( scanf("%d%d" , &n , &m)==2 ) 19 { 20 for( int i=1;i<=n;i++ ) scanf("%d" , &val[i]); 21 22 while( !Min_Q.empty() ) Min_Q.pop() ; 23 while( !Max_Q.empty() ) Max_Q.pop() ; 24 25 int p = 0 , rank = 1 , v ; 26 27 for( int i=1;i<=m;i++ ){ 28 29 30 scanf("%d" , &v) ; 31 32 while( v>p ){ 33 int num = val[++p] ; 34 35 if( Max_Q.size()<rank-1 ) Max_Q.push( num ) ; 36 37 else if( Max_Q.empty() || num>=Max_Q.top() ){ 38 Min_Q.push( num ) ; 39 } 40 else{ 41 Min_Q.push( Max_Q.top() ); 42 Max_Q.pop() ; 43 Max_Q.push( num ) ; 44 } 45 } 46 47 printf("%d\n" , Min_Q.top()) ; 48 Max_Q.push( Min_Q.top() ) ; 49 Min_Q.pop() ; 50 rank++ ; 51 } 52 } 53 }
2:treap, 模板题。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 7 const int N = 33333 ; 8 9 using namespace std ; 10 11 int val[N] , n , m , ans ; 12 13 struct node{ 14 node * ch[2] ; 15 int s , v , r ; 16 node(){ 17 ch[0] = ch[1] = NULL ; 18 s = 1 ; 19 } 20 int cmp( int x )const{ 21 if( x==v ) return -1 ; 22 return x<v?0:1 ; 23 } 24 void maintain(){ 25 s = 1 ; 26 if( ch[0]!=NULL ) s += ch[0]->s ; 27 if( ch[1]!=NULL ) s += ch[1]->s ; 28 } 29 }; 30 31 void rotate( node * &o , int d ){ 32 node * k = o->ch[d^1] ; 33 o->ch[d^1] = k->ch[d] ; 34 k->ch[d] = o ; 35 o->maintain() ; k->maintain() ; 36 o = k ; 37 } 38 39 bool find_x( node * o , int x ){ 40 while( o!=NULL ){ 41 int d = o->cmp(x) ; 42 if( d==-1 ) return true ; 43 else o = o->ch[d] ; 44 } 45 return false ; 46 } 47 48 void insert( node * &o , int x ){ 49 if( o==NULL ){ 50 o = new node() ; 51 o->v = x ; o->r = rand() ; 52 return ; 53 } 54 55 int d = o->cmp(x) ; 56 57 if( d==-1 ) d = 1 ; 58 insert( o->ch[d] , x ) ; 59 if( o->ch[d]->r > o->r ) rotate( o , d^1 ) ; 60 o->maintain() ; 61 } 62 63 bool findkth( node * o , int k ){ 64 while( o!=NULL ){ 65 if( o->s<k ) return false ; 66 int l = o->ch[0]!=NULL ? o->ch[0]->s : 0 ; 67 68 if( l+1==k ){ 69 ans = o->v ; 70 return true ; 71 } 72 73 int d = l<k ; 74 o = o->ch[d] ; 75 k -= d*(l+1) ; 76 } 77 return false ; 78 } 79 80 int main() 81 { 82 while( scanf("%d%d" , &n , &m)==2 ){ 83 for( int i=1;i<=n;i++ ) scanf("%d" , &val[i]) ; 84 85 int p = 0 , rank = 1 , v; 86 87 node * root = NULL ; 88 for( int i=1;i<=m;i++ ){ 89 scanf("%d" , &v); 90 91 while( v>p ) insert( root , val[++p] ) ;//, cout<<p<<" "<<val[p]<<endl; 92 93 if( findkth( root , rank++ )==true ) 94 printf("%d\n" , ans); 95 } 96 } 97 }