题意:
设计一个数据结构,初始为空,支持以下操作:
(1)增加一个元素,要求在log(n)时间内完成,其中n是该数据结构中当前元素的个数。注意:数据结构中允许有重复的元素。
(2)返回当前元素集合的中位数,要求在常数时间内完成。如果当前元素的个数为偶数,那么返回下中位数(即两个中位数中较小的一个)。
(3)删除中位数,要求在log(n)时间内完成。
输入输入的第一行是一个自然数T,代表测试数据的组数((1 ≤ T ≤ 600))。每组测试数据的第一行是个自然数N,代表操作的次数,1<=N<=10000。后面的N行中的每行代表一个操作,每次操作首先输入一个单字符代表操作的类型:
I表示插入,后面跟着输入一个正整数(这是唯一带有输入数值的操作)。
Q表示查询,输出当前的中位数(这是唯一产生输出的操作)。
D表示删除当前的中位数。
输入保证是正确的:查询时集合保证不为空(即中位数是存在的),删除时保证集合中有足够可供删除的元素。输出每次查询操作Q时输出的中位数,每次输出单独占一行。
样例输入
1 8 I 4 I 3 I 5 Q D I 10 I 2 Q
样例输出
4
3
思路:
维护两个堆,一个小顶堆(存放大于中位数的数),一个大顶堆(存放小于或等于中位数的数)。保持大顶堆的元素个数和小顶堆的元素个数相等(元素总数为偶数)或者大顶堆元素个数比小顶堆的元素个数多一个(元素总数为奇数)。此时,下中位数即为大顶堆堆顶元素。
实现:
1 #include <cstdio> 2 #include <iostream> 3 #include <functional> 4 #include <queue> 5 using namespace std; 6 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 int T, n, d; 11 char c; 12 cin >> T; 13 while (T--) 14 { 15 priority_queue<int, vector<int>, greater<int>> minq; 16 priority_queue<int> maxq; 17 cin >> n; 18 int cnt = 0; 19 for (int i = 0; i < n; i++) 20 { 21 cin >> c; 22 if (c == 'I') 23 { 24 cin >> d; 25 if (cnt == 0) 26 { 27 maxq.push(d); 28 } 29 else if (d > maxq.top()) 30 { 31 if (cnt & 1) 32 { 33 minq.push(d); 34 } 35 else 36 { 37 minq.push(d); 38 maxq.push(minq.top()); 39 minq.pop(); 40 } 41 } 42 else 43 { 44 if (cnt & 1) 45 { 46 maxq.push(d); 47 minq.push(maxq.top()); 48 maxq.pop(); 49 } 50 else 51 { 52 maxq.push(d); 53 } 54 } 55 cnt++; 56 } 57 else if (c == 'Q') 58 { 59 cout << maxq.top() << endl; 60 } 61 else 62 { 63 if (cnt & 1) 64 { 65 maxq.pop(); 66 } 67 else 68 { 69 maxq.pop(); 70 maxq.push(minq.top()); 71 minq.pop(); 72 } 73 cnt--; 74 } 75 } 76 } 77 return 0; 78 }