感受
权值线段树模板题,随便搞一搞


思路
很显然,每次往后推一个数时,只要求出已覆盖数的第k大,明显就是板子题目呀!
叶子节点维护的是小与等于这个权值的有多少个,可以离散化乱搞


#include <bits/stdc++.h>
#define ls o << 1
#define rs o << 1 | 1
using namespace std;
typedef long long ll;
const int maxn = 1e4+ 10;
vector<int> vec;
int a[maxn << 2];///叶子节点表示小与等于这个权值的有多少个
int b[maxn];
int c[maxn];
void up(int o){
    a[o] = a[ls] + a[rs];
}
void update(int o, int l, int r, int x){
    if(l == r){
        a[o]++;
        return ;
    }
    int mid = (l + r) / 2;
    if(x <= mid) update(ls, l, mid, x);
    else update(rs, mid + 1, r, x);
    up(o);
}
int num;
void query(int o, int l, int r, int k){
    if(l == r){
        num = l;
        return ;
    }
    int mid = (l + r) / 2;
    if(k > a[ls]) query(rs, mid + 1, r, k - a[ls]);
    else query(ls, l, mid, k);
}
int main(){
    int t;
    int opt, m;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d", &opt, &m);
        for(int i = 1; i <= m; i++){
            scanf("%d", &c[i]);
            b[i] = c[i];
        }
        sort(b + 1, b + m + 1);
        memset(a, 0, sizeof(a)); vec.clear();
        for(int i = 1; i <= m; i++){
            int pos = lower_bound(b + 1, b + m + 1, c[i]) - b;
            update(1, 1, m, pos);
            if(i & 1){
                query(1, 1, m, (i + 1) / 2);
                vec.push_back(b[num]);
            }
        }
        num = vec.size();
        printf("%d %d\n", opt, num);
        int pp = 0;
        for(int i = 0; i < num; i++){
            printf("%d", vec[i]); pp++;
            if(pp % 10 && i != num - 1){
                putchar(' ');
            }
            else{
                putchar('\n'); pp = 0;
            }
        }
    }
    return 0;
}