HDU 5249:KPI(权值线段树)

KPI

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度。数十亿的请求被推到一个大管道后同时服务从管头拉取请求。让我们来定义每个请求都有一个重要值。我的KPI是由当前管道内请求的重要值的中间值来计算。现在给你服务记录,有时我想知道当前管道内请求的重要值得中间值。
 

 

Input
有大约100组数据。

每组数据第一行有一个n(1n10000),代表服务记录数。

接下来有n行,每一行有3种形式
  "in x": 代表重要值为x(0x109)的请求被推进管道。
  "out": 代表服务拉取了管道头部的请求。
  "query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,如果当前管道内有m条请求, 我想知道,升序排序后第floor(m/2)+1th 条请求的重要值.

为了让题目简单,所有的x都不同,并且如果管道内没有值,就不会有"out"和"query"操作。
 

 

Output
对于每组数据,先输出一行

Case #i:
然后每一次"query",输出当前管道内重要值的中间值。
 

 

Sample Input
6
in 874
query
out
in 24622
in 12194
query
 

 

Sample Output
Case #1:
874
24622
 

算法:权值线段树

题解:此题需要先离散化,然后根据权值线段树的特点,依次更新每个区间数的个数,然后根据个数查询即可,题中的拉取了管道头部,直接用队列模拟就好。

 

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

const int maxn = 1e5+7;

struct query {
    int op;
    int val;
}Q[maxn];

struct tree {
    int l, r, s;
}tree[maxn << 2];


vector<int> v;
int n;
int len;

int find(int x) {
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}

void init() {
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    len = v.size();
}

void build(int root, int l, int r) {
    tree[root].l = l;
    tree[root].r = r;
    tree[root].s = 0;
    if(l == r) {
        return;
    }
    int mid = (l + r) >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
}

void update(int root, int pos, int val) {
    int l = tree[root].l;
    int r = tree[root].r;
    tree[root].s += val;
    if(l == r) {
        return;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) {
        update(root << 1, pos, val);
    } else {
        update(root << 1 | 1, pos, val);
    }
}

int query(int root, int k) {
    int l = tree[root].l;
    int r = tree[root].r;
    if(l == r) {
        return l;
    }
    int sum = tree[root << 1].s;
    if(sum >= k) {
        return query(root << 1, k);
    } else {
        return query(root << 1 | 1, k - sum);
    }
}

int main() {
    int cas = 0;
    while(~scanf("%d", &n)) {
        for(int i = 1; i <= n; i++) {
            char str[10];
            scanf("%s", str);
            if(str[0] == 'i') {
                Q[i].op = 1;
                scanf("%d", &Q[i].val);
                v.push_back(Q[i].val);
            } else if(str[0] == 'o') {
                Q[i].op = 2;
            } else {
                Q[i].op = 3;
            }
        }
        init();
        build(1, 1, len);
        queue<int> que;     //此队列模拟进出数据
        printf("Case #%d:\n", ++cas);
        for(int i = 1; i <= n; i++) {
            if(Q[i].op == 1) {
                int pos = find(Q[i].val);
                update(1, pos, 1);
                que.push(pos);      
            } else if(Q[i].op == 2) {
                update(1, que.front(), -1);
                que.pop();
            } else {
                int k = (que.size() / 2) + 1;
                int pos = query(1, k);
                printf("%d\n", v[pos - 1]);
            }
        }
    }
    return 0;
}

 

posted @ 2019-08-02 10:28  不会fly的pig  阅读(303)  评论(1编辑  收藏  举报