题意
传送门 NC 50940
题解
堆
小根堆维护元素中较大的一半,大根堆维护元素中较小的一半。
若元素值大于小根堆的堆顶元素,则插入小根堆;若元素值小于大根堆的堆顶元素,则插入大根堆。若出现其中一个堆比另一个堆的元素数大 2 2 2 个,则将元素数量较大的堆的堆顶元素弹出,插入另一个堆。中位数即元素数量较大的堆顶元素。
#include <bits/stdc++.h>
using namespace std;
#define maxn 10005
int a[maxn];
int main()
{
int p, t, m;
scanf("%d", &p);
while (p--)
{
scanf("%d%d", &t, &m);
printf("%d %d\n", t, m / 2 + 1);
for (int i = 0; i < m; i++)
{
scanf("%d", a + i);
}
priority_queue<int> bq;
priority_queue<int, vector<int>, greater<int>> sq;
for (int i = 0, j = 0; i < m; i++)
{
if (!sq.empty() && a[i] > sq.top())
{
sq.push(a[i]);
}
else
{
bq.push(a[i]);
}
if (bq.size() > sq.size() + 1)
{
sq.push(bq.top());
bq.pop();
}
if (sq.size() > bq.size() + 1)
{
bq.push(sq.top());
sq.pop();
}
if (!(i & 1))
{
++j;
printf("%d ", sq.size() > bq.size() ? sq.top() : bq.top());
}
if (j == 10 || i == m - 1)
{
putchar('\n');
j = 0;
}
}
}
}
BIT
坐标离散化,树状数组维护小于等于自身值的数字数量。设当前数列数量为 n n n,按位枚举可以在 O ( l o g m ) O(logm) O(logm) 内求 s u m sum sum 为 n / 2 + 1 n/2+1 n/2+1 的下标,即中位数的离散值。
#include <bits/stdc++.h>
using namespace std;
#define maxn 10005
int p, t, m, a[maxn], s[maxn], mp[maxn], bit[maxn];
void add(int i, int x)
{
while (i <= m)
{
bit[i] += x;
i += i & -i;
}
}
int seeksum(int x)
{
int res = 0, sum = 0;
for (int i = 14; i >= 0; i--)
{
res += 1 << i;
if (res > m || sum + bit[res] >= x)
res -= 1 << i;
else
sum += bit[res];
}
return res + 1;
}
void compress(int *x, int *s)
{
vector<int> xs(m);
for (int i = 0; i < m; i++)
{
xs[i] = x[i];
}
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(), xs.end()), xs.end());
for (int i = 0; i < m; i++)
{
s[i] = lower_bound(xs.begin(), xs.end(), x[i]) - xs.begin() + 1;
mp[s[i]] = x[i];
}
}
int main()
{
scanf("%d", &p);
while (p--)
{
scanf("%d%d", &t, &m);
printf("%d %d\n", t, m / 2 + 1);
for (int i = 0; i < m; i++)
{
scanf("%d", a + i);
}
memset(bit, 0, sizeof(bit));
compress(a, s);
for (int i = 0, j = 0; i < m; i++)
{
add(s[i], 1);
if (!(i & 1))
{
++j;
int k = seeksum(j);
printf("%d ", mp[k]);
if (j % 10 == 0 || i == m - 1)
{
putchar('\n');
}
}
}
}
}