poj 1442 Black Box(优先队列&Treap)
题目链接:http://poj.org/problem?id=1442
思路分析:
<1>维护一个最小堆与最大堆,最大堆中存储最小的K个数,其余存储在最小堆中;
<2>使用Treap构造名次树,查询第K大数即可;
代码如下(堆的用法):
#include<iostream> #include<queue> using namespace std; struct cmp1 { bool operator() ( const int a, const int b ) { return a > b; } }; struct cmp2 { bool operator()( const int a, const int b ) { return a < b; } }; priority_queue<int,vector<int>,cmp1>MaxHeap; priority_queue<int,vector<int>,cmp2>MinHeap; int a[30000]; int main() { int m, n, i, K; int Count = 0, Tmp; scanf( "%d%d", &m, &n ); for ( i = 0; i < m; i++ ) scanf( "%d", &a[i] ); for( i = 0; i < n; i++ ) { scanf( "%d", &K ); while ( Count < K ) { MaxHeap.push(a[Count]); if( !MinHeap.empty() && MaxHeap.top() < MinHeap.top() ) { Tmp = MaxHeap.top(); MaxHeap.pop(); MaxHeap.push( MinHeap.top() ); MinHeap.pop(); MinHeap.push(Tmp); } Count++; } printf( "%d\n", MaxHeap.top() ); MinHeap.push( MaxHeap.top() ); MaxHeap.pop(); } }
代码如下(Treap):
#include <cstdio> #include <ctime> #include <cstring> #include <iostream> using namespace std; const int MAX_N = 300000 + 100; int add[MAX_N]; struct Node{ Node *ch[2]; int value, key; int size; int cmp(int x) const{ if (x == value) return -1; return x < value ? 0 : 1; } void Maintain(){ size = 1; if (ch[0] != NULL) size += ch[0]->size; if (ch[1] != NULL) size += ch[1]->size; } }; 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){ if (o == NULL){ o = new Node(); o->ch[0] = o->ch[1] = NULL; o->value = x; o->key = rand(); } else{ int d = (x < (o->value) ? 0 : 1); Insert(o->ch[d], x); if (o->ch[d]->key > o->key) Rotate(o, d ^ 1); } o->Maintain( ); } void Remove(Node *&o, int x){ int d = o->cmp(x); if (d == -1){ if (o->ch[0] == NULL) o = o->ch[1]; else if (o->ch[1] == NULL) o = o->ch[0]; else{ int d2 = (o->ch[0]->key > o->ch[1]->key ? 1 : 0); Rotate(o, d2); Remove(o->ch[d2], x); } } else Remove(o->ch[d], x); } int Find(Node *o, int x){ while (o != NULL){ int d = o->cmp(x); if (d == -1) return 1; else o = o->ch[d]; } return 0; } int FindKth(Node *o, int k){ int l_size = (o->ch[0] == NULL ? 0 : o->ch[0]->size); if (k == l_size + 1) return o->value; else if (k <= l_size) return FindKth(o->ch[0], k); else return FindKth(o->ch[1], k - l_size - 1); } int main() { int m, n, k; Node *root = NULL; srand(100); scanf("%d %d", &m, &n); for (int i = 1; i <= m; ++i) scanf("%d", &add[i]); int j = 1; for (int i = 1; i <= n; ++ i){ scanf("%d", &k); for (; j <= k; ++j) Insert(root, add[j]); printf("%d\n", FindKth(root, i)); } return 0; }