欢迎来到ydclyq的博客

我是一只摆烂小狗,欢迎来到摆烂小狗的世界,我们一起摆烂吧

洛谷 P1801 黑匣子_NOI导刊2010提高(06) 题解

昨晚恶补了一下二叉堆的内容

然后就找了几个二叉堆的题来做awa

然后发现用二叉堆做这题复杂度是O(nlogn)

但是有O(n)的解法

某大佬这么说

思路大概就是:

利用一个大根堆一个小根堆来维护第k小,并没有强制在线

不强制在线,所以我们直接读入所有元素,枚举询问,因为

要询问第k小,所以把前面的第k个元素都放进大根堆里面,

然后如果元素数量大于k,就把堆顶弹掉放到小根堆里面,

使大根堆的元素严格等于k,这样这次询问的结果就是小根

堆的堆顶了(前面k-1小的元素都在大根堆里面了)

记得在完成这次询问后重新把小根堆的堆顶放到大根堆里面就好

详见代码:

#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#define ll long long
#define inf 1<<30
#define il inline
#define in1(a) read(a)
il int max(int x,int y) {
    return x>y?x:y;
}
il int min(int x,int y) {
    return x<y?x:y;
}
il int abs(int x) {
    return x>0?x:-x;
}
il void swap(int &x,int &y) {
    int t=x;
    x=y,y=t;
}
il void readl(ll &x) {
    x=0;
    ll f=1;
    char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-')f=-f;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    x*=f;
}
il void read(int &x) {
    x=0;
    int f=1;
    char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-')f=-f;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    x*=f;
}
//上边大部分并没有用
using namespace std;
#define N 200010
priority_queue<int,vector<int>,greater<int> > q;
priority_queue<int> q1;
int n,m,a[N],b[N];
int main() {
    in1(n),in1(m);
    for(int i=1; i<=n; i++)in1(a[i]);
    for(int i=1; i<=m; i++)in1(b[i]);
    int i=1;
    for(int j=1; j<=m; j++) {
        for(; i<=b[j]; i++) {
            q1.push(a[i]);
            if(q1.size()==j)q.push(q1.top()),q1.pop();
        }
        printf("%d\n",q.top());
        q1.push(q.top());
        q.pop();
    }
    return 0;
}
View Code

 

posted @ 2019-10-17 16:19  ydclyq  阅读(132)  评论(1编辑  收藏  举报