题意
求给定数组的动态中位数(时的中位数)。
分析
求中位数,不就相当于求当前数列的第 大吗?
于是自然地想到了权值线段树。
权值线段树可以在 内找到第
大值。
不过在此题中,由于空间限制很紧,不能用动态开点,而需要先离散化。
代码如下
#include <bits/stdc++.h>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define N 10000
using namespace __gnu_pbds;
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
LL z = 1;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
int ksm(int a, int b, int p){
int s = 1;
while(b){
if(b & 1) s = z * s * a % p;
a = z * a * a % p;
b >>= 1;
}
return s;
}
int a[N], b[N], sum[N * 2];
void update(int l, int r, int rt, int p, int c){
sum[rt] += c;
if(l == r) return;
int m = l + r >> 1;
if(p <= m) update(lson, p, c);
else update(rson, p, c);
}
int find(int l, int r, int rt, int x){
if(l == r) return l;
int m = l + r >> 1;
if(x <= sum[rt << 1]) return find(lson, x);
return find(rson, x - sum[rt << 1]);
}
int main(){
int i, j, T, n, m, tot = 0, ans;
T = read();
while(T--){
memset(sum, 0, sizeof(sum));
j = read(); n = read();
printf("%d %d\n", j, (n + 1) / 2);
for(i = 1; i <= n; i++) a[i] = read(), b[i] = a[i];
sort(b + 1, b + n + 1);
m = unique(b + 1, b + n + 1) - b - 1;
for(i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b;
tot = 0;
for(i = 1; i <= n; i++){
update(1, m, 1, a[i], 1);
j = (i + 1) / 2;
if(i % 2){
tot++;
ans = b[find(1, m, 1, j)];
printf("%d ", ans);
if(tot == 10 && i < n) tot = 0, printf("\n");
}
}
printf("\n");
}
return 0;
}

京公网安备 11010502036488号