题目链接
http://poj.org/problem?id=3784
分析
离线做法,先将整个序列读入,由此得到链表,且链表元素有序,可知中位数及其位置。
倒序扫描原序列,依次从链表中删除对应元素。
每次删除,讨论链表长度的奇偶性以及中位数和要删除元素的位置关系,可更新中位数位置。
应用了链表可以 O ( 1 ) O(1) O(1) 删除元素的性质。
AC代码
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read() {
int num = 0, flag = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') flag = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return flag * num;
}
const int maxm = 1e4 + 5;
struct Node {
int id, l, r, v;
bool operator < (const Node& rhs) const {
return v < rhs.v;
}
} l[maxm];
int a[maxm], ans[maxm];
int main() {
int P = read();
while (P--) {
int id = read(), m = read();
for (int i = 1; i <= m; ++i)
l[i].id = i, l[i].v = read();
sort(l + 1, l + m + 1);
for (int i = 1; i <= m; ++i) a[l[i].id] = i;
for (int i = 1; i <= m; ++i)
l[i].l = i - 1, l[i].r = i + 1;
int p = m / 2 + 1, median = l[p].v;
for (int i = m; i >= 1; --i) {
Node x = l[a[i]];
if (i & 1) {
ans[i] = median;
if (a[i] >= p) p = l[p].l, median = l[p].v;
l[x.l].r = x.r, l[x.r].l = x.l;
} else {
if (a[i] <= p) p = l[p].r, median = l[p].v;
l[x.l].r = x.r, l[x.r].l = x.l;
}
}
printf("%d %d", id, m / 2 + 1);
for (int i = 1; i <= m; ++i) {
if (i % 20 == 1) puts("");
if (i & 1) printf("%d ", ans[i]);
}
if (P) puts("");
}
return 0;
}