题目:

往一个空序列加个数。当序列中数的个数为奇数个时,记录此时序列排序后的中位数。输出所有中位数。


做法:

看到中位数,第一时间想到权值线段树。所以我们先将所有数读进来离线处理。
先将所有数离散化,便与用线段树维护。
然后一个一个数加到序列中,线段树该数字出现的次数+1。奇数个数时,线段树上查询第小的数,这就是我们需要的中位数。
然后按题目要求输出就行了。


代码:

#include <bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 2e4 + 7;
int n, m, a[N];
vector<int> v, ans;
int T[N<<2];
int get(int x){
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
void update(int pos, int l, int r, int rt){
    if (l == r){
        T[rt]++; return;
    }
    int mid = (l+r) >> 1;
    if (pos <= mid) update(pos, l, mid, lson);
    else update(pos, mid+1, r, rson);
    T[rt] = T[lson]+T[rson];
}
int query(int k, int l, int r, int rt){
    if (l == r) return l;
    int mid = (l+r) >> 1;
    if (k <= T[lson]) return query(k, l, mid, lson);
    else return query(k-T[lson], mid+1, r, rson);
}
int main(void){
    IOS;
    int Te, t; cin >> Te;
    while (Te--){
        cin >> t >> n;
        v.clear(); ans.clear();
        memset(T, 0, sizeof T);
        for (int i = 1; i <= n; ++i){
            cin >> a[i];
            v.push_back(a[i]);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        m = v.size();
        for (int i = 1; i <= n; i++){
            update(get(a[i]), 1, m, 1);
            if (i%2 == 1){
                int t = query(i/2+1, 1, m, 1);
                ans.push_back(v[t-1]);
            }
        }
        cout << t << ' ' << ans.size() << endl;
        for (int i = 0; i < ans.size(); ++i){
            if (i && i%10 == 0) cout << endl;
            cout << ans[i] << ' ';
        }
        cout << endl;
    }
    return 0;
}