#链表 or 堆,对顶堆#poj 3784 Running Median

题目

动态求中位数


分析(离线)

这道题可以用链表做,倒着推,一个个从链表内删除,求中位数之前需要排序,当然需要标记每个数在链表出现的位置


链表代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#define mod 10007
struct rec{
    int val,id;
    bool operator<(const rec &x)const{
        return val<x.val;
    }
}a[mod];
int t,n,f[mod],l[mod],r[mod],ans[mod];
int in(){
    int ans=0,f=1; char c=getchar();
    while ((c<48||c>57)&&c!='-') c=getchar();
    if (c=='-') f=-f,c=getchar();
    while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
void print(int ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
int main(){
    t=in();
    while (t--){
        int v=in(); n=in(); int k=n+1>>1; 
        print(v); putchar(' '); print(k); 
        putchar('\n'); int tv=0,mid=k;
        for (int i=1;i<=n;i++) a[i].val=in(),a[i].id=i;
        std::stable_sort(a+1,a+1+n); r[0]=1; l[n+1]=n;
        for (int i=1;i<=n;i++) f[a[i].id]=i,l[i]=i-1,r[i]=i+1;//快排&&建链表
        for (int i=n;;i-=2){
            if (i&1) ans[++tv]=a[mid].val;//中位数
            if (i==1) break;
            if (f[i]>=mid&&f[i-1]>=mid) mid=l[mid];//中位数在左边
            else if (f[i]<=mid&&f[i-1]<=mid) mid=r[mid];//中位数在右边
            l[r[f[i]]]=l[f[i]]; r[l[f[i]]]=r[f[i]]; 
            l[r[f[i-1]]]=l[f[i-1]]; r[l[f[i-1]]]=r[f[i-1]];//删除
        }
        for (int i=k;i>=1;i--){
            if (ans[i]<0) putchar('-'),ans[i]=-ans[i];
            if (ans[i]) print(ans[i]); 
            else putchar('0');
            if ((k-i)%10==9||i==1) putchar('\n'); else putchar(' '); 
        }
    }
    return 0;
}

分析(在线)

也可以用对顶堆的方式,小根堆的堆顶就是中位数


优先队列代码

#include <cstdio>
#include <queue>
std::priority_queue<int>q1,q2;
int in(){
    int ans=0,f=1; char c=getchar();
    while ((c<48||c>57)&&c!='-') c=getchar();
    if (c=='-') f=-f,c=getchar();
    while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
void print(int ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
int main(){
    int t=in();
    while (t--){
        int n=in(),tv=0; print(n); putchar(' ');
        n=in(); int k=n+1>>1; print(k); putchar('\n');
        while (q1.size()) q1.pop();//清空
        while (q2.size()) q2.pop();
        for (int i=1;i<=n;i++){
            int x=in();
            if (i&1) q1.push(-x); else q2.push(x);//q1取相反数可改成小根堆
            while (q1.size()&&q2.size()&&-q1.top()<q2.top()){//修改堆顶
                int x=-q1.top(); q1.pop();
                q1.push(-q2.top());
                q2.pop(); q2.push(x); 
            }
            if (i&1) {
                if (q1.top()>0) putchar('-'),print(q1.top());
                else if (q1.top()<0) print(-q1.top()); 
                else putchar('0');
                if (i!=n&&i%20==19) putchar('\n'); else putchar(' ');
            }
        }
        putchar('\n');
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/81744582
今日推荐