解析:
题意要求动态的求中位数,参考别人的方法是先开两个优先队列。
以及利用一个队列来模拟管道。
然后左边升序,右边降序,右边个数-左边个数>=1,然后右边询问的时候直接输出右边最小的,然后看看是左边还是右边的,把对应的那边的个数-1,如果发现(右边个数-左边个数>=1)这个条件不满足了,那么就权衡下,两个队列里面的元素处理下(左给右或者右给左),总的时间复杂度与数据无关,是O(n*log(n))。
AC代码:
#include <cstdio>
#include <cstring>
#include <set>
#include <queue>
using namespace std;
set<int> stL, stR;
set<int>::iterator it;
queue<int> que;
char cmd[10];
int q;
void modify() {
int dis = stL.size() - stR.size();
if(dis == 0 || dis == 1) return ;
if(dis == -1) { //右边比左边多一个,右边移动一个到左边
it = stR.begin();
stL.insert(*it);
stR.erase(it);
}else if(dis == 2) { //左边多两个,左边移动一个到右边
it = stL.end(); it--;
stR.insert(*it);
stL.erase(it);
}
}
void pushVal(int x) {
que.push(x);
if(stL.size() == 0) {
stL.insert(x);
}
it = stL.end();
it--;
if(x <= *it) stL.insert(x);
else stR.insert(x);
modify();
}
void popVal() {
int front = que.front();
que.pop();
it = stL.end(), it--;
int last = *it;
if(front <= last) {
it = stL.find(front);
stL.erase(it);
}else {
it = stR.find(front);
stR.erase(it);
}
modify();
}
void query() {
int tot = stL.size() + stR.size();
if(tot & 1) {
it = stL.end(); it--;
}else {
it = stR.begin();
}
printf("%d\n", *it);
}
int main() {
int cas = 1;
while(scanf("%d", &q) != EOF) {
stL.clear(), stR.clear();
while(!que.empty()) que.pop();
printf("Case #%d:\n", cas++);
int x;
while(q--) {
scanf("%s", cmd);
if(cmd[0] == 'i') {
scanf("%d", &x);
pushVal(x);
}else if(cmd[0] == 'o') {
popVal();
}else if(cmd[0] == 'q') {
query();
}
}
}
return 0;
}