hdu 5249 KPI (动态中位数,两个set)

来源:互联网 发布:知乎沙发挑选 编辑:程序博客网 时间:2024/05/16 07:34

解析:

题意要求动态的求中位数,参考别人的方法是先开两个优先队列。
以及利用一个队列来模拟管道。
然后左边升序,右边降序,右边个数-左边个数>=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;}
0 0
原创粉丝点击