题目描述

For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output the median (middle value) of the elements received so far.


题解

有两种方法第一种就是直接离散化后,用权值线段树查询第k大就行。这里主要说一下第二种,也就是对顶堆做法,
顾名思义,对顶的堆:一个最小值在前qq,一个最大值在前q,那么我们在不断插入数据的时候只要一直维护q最大值小于qq中最小值,并且q.size()==qq.size() OR q.size()==qq.size()+1即可

对顶堆代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define pb push_back
#define fi first
#define se second
#define ios ios::sync_with_stdio(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int maxn = 4e5 + 6;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
LL qp(LL x,LL y){LL ans=1;x%=mod;while(y){if(y&1) ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}
LL inv(LL x){return qp(x,mod-2);}
//head

int t,n,m,a[maxn],ans[maxn];
priority_queue<int>q;
priority_queue<int,vector<int>,greater<int> >qq;
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) scanf("%d",&a[i]);
        while(q.size()) q.pop();
        while(qq.size()) qq.pop();
        int cnt=0;
        printf("%d %d\n",n,(m+1)/2);

        for(int i=1;i<=m;i++){
             if(i&1) q.push(a[i]);
             else qq.push(a[i]);
             if(i>=2){
                if(q.top()>qq.top()){
                    int x=q.top(),y=qq.top();
                    q.pop();qq.pop();
                    q.push(y);qq.push(x);
                }
             }
             if(i&1) ans[++cnt]=q.top();
        }

        for(int i=1;i<=cnt;i++){
            printf("%d",ans[i]);
            if(i%10==0) printf("\n");
            else {
                if(i==cnt) printf("\n");
                else printf(" ");
            }
        }
    }
}

权值线段树代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define pb push_back
#define fi first
#define se second
#define ios ios::sync_with_stdio(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int maxn = 4e5 + 6;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
LL qp(LL x,LL y){LL ans=1;x%=mod;while(y){if(y&1) ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}
LL inv(LL x){return qp(x,mod-2);}
//head

int t,n,m,a[maxn],b[maxn],ans[maxn];
int sum[maxn];
void update(int rt,int l,int r,int pos){
     if(l==r) {sum[rt]++;return ; }

     int mid=(l+r)>>1;
     if(pos<=mid) update(rt<<1,l,mid,pos);
     else update(rt<<1|1,mid+1,r,pos);
     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

int ask(int rt,int l,int r,int pos){
    if(l==r){return l;}
    int mid=(l+r)>>1,cnt=sum[rt<<1];
    if(pos<=cnt) return ask(rt<<1,l,mid,pos);
    else return ask(rt<<1|1,mid+1,r,pos-cnt);
}

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) scanf("%d",&a[i]),b[i]=a[i];
        printf("%d %d\n",n,(m+1)/2);
        sort(b+1,b+1+m);
        n=unique(b+1,b+1+m)-b-1;
        int c=0;
        for(int i=1;i<=m;i++){
            update(1,1,n,lower_bound(b+1,b+1+n,a[i])-b);
            if(i&1){
                ans[++c]=b[ask(1,1,n,(i+1)/2)];
            }
        }

        for(int i=1;i<=c;i++){
            printf("%d",ans[i]);
            if(i%10==0) printf("\n");
            else {
                if(i==c) printf("\n");
                else printf(" ");
            }
        }
        for(int i=0;i<=4*n+10;i++) sum[i]=0;
    }
}