【对顶堆】 动态中位数

传送门

题意

\(p\)组数据,每组有一个长度为\(M\)的序列,依次读入一个序列中每一个值\(x_{i}\),当读取个数为奇数的时候输出中位数

数据范围

\(\begin{array}{l}1 \leq P \leq 1000 \\ 1 \leq M \leq 9999\end{array}\)

题意

建立两个堆,一个大根堆,一个小根堆,来维护整个序列升序,小根堆的元素个数个数多一个
插入过程:

  • 每次如果小根堆的为空插入小根堆

  • 如果当前插入的数小于小根堆堆顶部,插入大根堆

    • 判断两个堆的个数是否合法,不合法调换,小根堆堆顶的即当前的中位数

输出时判断是否已经输出\(10\)个来输出空格

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second 
#define ll long long
#define pb push_back
#define close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);


typedef pair<long long,long long> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef double db;


const ll mod=1e9+7;
const int N=1e5+10;

ll powmod(ll a,ll b,ll p)
{
    ll res=1;
    a%=p;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}

ll gcd(ll a,ll b) 
{
    return b?gcd(b,a%b):a;
}

int _,id,n,x;

void solve()
{
    cin>>id>>n;
    cout<<id<<' '<<(n+1)/2<<endl;
    int p=0;
    priority_queue<int,vector<int>,greater<int>>mi;
    priority_queue<int>mx;
    rep(i,1,n+1)
    {
        cin>>x;
        mi.push(x);
        if(mx.size() && mx.top()>mi.top())
        {
            int t=mi.top(),lt=mx.top();
            mi.pop();mx.pop();
            mi.push(lt);mx.push(t);
        }
        if(mi.size() > mx.size()+1)
        {
            mx.push(mi.top());
            mi.pop();
        }
        if(i&1)
            cout<<mi.top()<<(++p%10 == 0?'\n':' ');
    }
    if(p%10) cout<<endl;
}

int main()
{
    close;
    cin>>_;
    while(_--) solve();
}
posted @ 2020-09-21 21:37  Hyx'  阅读(118)  评论(0)    收藏  举报