Problem Description
你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度。数十亿的请求被推到一个大管道后同时服务从管头拉取请求。让我们来定义每个请求都有一个重要值。我的KPI是由当前管道内请求的重要值的中间值来计算。现在给你服务记录,有时我想知道当前管道内请求的重要值得中间值。
Input
有大约100组数据。
每组数据第一行有一个n(1≤n≤10000),代表服务记录数。
接下来有n行,每一行有3种形式
“in x”: 代表重要值为x(0≤x≤109)的请求被推进管道。
“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
思路
- 权值线段树:更普通的线段树差不多将元素存在对应区间的位置上,例如5就存在父节点(l == r == 5)的节点上,这样就能查找区间第K大的元素。
- 用两个set(内部递增排序)模拟,添加和删除操作之后都要保持左set的长度(m/2+1),这样方便询问的时候直接给出答案,而且不容易乱
// 权值线段树
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define maxn 10006
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
map<int, int> m1;
map<int, int> m2;
int seg[maxn << 2];
int a[maxn];
void pushup (int rt) {
seg[rt] = seg[lc] + seg[rc];
}
void insert (int rt, int l, int r, int x, int op) {
if (l == r) {
seg[rt] += op;
return;
}
if (mid >= x) insert(lc, l, mid, x, op);
else insert(rc, mid+1, r, x, op);
pushup(rt);
}
int query(int rt, int l, int r, int k) {
if (l == r) return l;
if (seg[lc] >= k) return query(lc, l, mid, k);
else return query(rc, mid+1, r, k - seg[lc]);
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
int n, d, Case = 1;
char s[10];
while (scanf("%d", &n) != EOF) {
printf("Case #%d:\n", Case++);
mem(seg, 0);
priority_queue<int> que;
queue<int> que2;
m1.clear();
m2.clear();
for (int i = 0; i < n; ++i) {
scanf("%s", s);
switch (s[0]) {
case 'i':
scanf("%d", &a[i]);
que.push(a[i]);
break;
case 'o':
a[i] = -1;
break;
case 'q':
a[i] = -2;
break;
}
}
int pos = que.size();
while (!que.empty()) {
m1[que.top()] = pos;
m2[pos] = que.top();
que.pop();
pos--;
}
for (int i = 0; i < n; ++i) {
if (a[i] >= 0) {
insert(1, 1, n, m1[a[i]], 1);
que2.push(a[i]);
}else if (a[i] == -1) {
insert(1, 1, n, m1[que2.front()], -1);
que2.pop();
}else {
pos = query(1, 1, n, que2.size()/2 + 1);
printf("%d\n", m2[pos]);
}
}
}
return 0;
}
// set模拟
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i < n; ++i)
#define maxn 100005
using namespace std;
set<int> st1, st2;
queue<int> que;
int main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
char s[10];
int n, d, m, Case = 0;
while (scanf("%d", &n) != EOF) {
printf("Case #%d:\n", ++Case);
while (!que.empty()) que.pop();
st1.clear();
st2.clear();
m = 0;
for (int i = 0; i < n; ++i) {
scanf("%s", s);
if (s[0] == 'i') {
scanf("%d", &d);
if (st1.empty() || *st1.rbegin() > d) st1.insert(d);
else st2.insert(d);
que.push(d);
m++;
}else if (s[0] == 'q') {
printf("%d\n", *st1.rbegin());
}else {
int tmp = que.front();
que.pop();
if (st1.find(tmp) != st1.end()) st1.erase(tmp);
else st2.erase(tmp);
m--;
}
while (m > 0 && st1.size() > m/2 + 1) {
d = *st1.rbegin();
st2.insert(d);
st1.erase(d);
}
while (m > 0 && st1.size() < m/2 + 1) {
d = *st2.begin();
st1.insert(d);
st2.erase(d);
}
}
}
return 0;
}