序列合并,洛谷之提高历练地,堆

版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/79957859

正文

      第三题:序列合并

      我们很容易就可以得到一个结论,将A,B从小到大排序后,可以满足A1+B1<=A1+B2<=A1+B3...

      我们也可以满足A1+B1<=A2+B1<=A3+B1...

      那么我们选出一个最小的,那么第二小的只可能存在于Ai+1 + Bj   或者   Ai + Bj+1;%%%

      所以我们排一次序后,把A1+B1到A1+Bn扔进堆里,然后保证大根堆里面有n个的情况下,不断往里面塞最小值,然后倒序输出即可。

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

int n;
int a[100010],b[100010];
priority_queue<int> f;
int t[100010];

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    sort(a+1,a+1+n);
    sort(b+1,b+1+n);
    for(int i=1;i<=n;i++)
        f.push(a[1]+b[i]);
    for(int i=2;i<=n;i++){
        for(int j=1;j<=n;j++){
            int x=a[i]+b[j];
            if(f.top()<=x) break;//比堆顶还要大就直接出来;
            f.pop();//如果不是,则更换堆顶
            f.push(x);
        }
    }
    int tt=0;
    while(!f.empty()){
        t[++tt]=f.top();
        f.pop();
    }
    for(int i=tt;i>=1;i--)
        printf("%d ",t[i]);
}


阅读更多

没有更多推荐了,返回首页