P1631 序列合并

https://www.luogu.org/blogAdmin/article/list?pageType=list[神奇连接嘤嘤嘤](https://www.luogu.org/problemnew/show/P1631)
这两天疯狂刷二叉堆的题目哈,但是头绪还是不够明朗嘤嘤嘤 ,基本就是必须要粗略看一下别人的思路,然后才能渐渐自己做出来。。。
那分析一下这道题,因为数据过大,so暴力枚举拿满分肯定是不现实的,那既然用堆,当然也不能把所有情况算出来在入堆,那跟暴力岂不是没区别??所以我们需要分析一下这道题
首先,排序我就不说了(正常看到无序数组想到排序还是很正常的),那么之后呢,就是对两个数组进行分析
那么既然a数组排过序了,很显然,最小值一定是(a[1]+b[1],a[1]+b[2],a[1]+b[3]......a[1]+b[n])中的一个,因为a[1]是a数组中最小的一个,而b数组中最小的一个也必定在b[1]到b[n]中,所以以上n个数中一定会出现最小值,我们定义一个结构体小根堆,将b[i]对应相加的a[j]的j以及a[j]+b[i]的值记录在小根堆中,每输出一个,就将记录下标为i的b数组对应的a数组的下标++,以此类推,输出n个之后结束
实际上,这还是很好实现的嘤嘤嘤~~~

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

int n;
int z[100005],y[100005],zy[100005];
struct node{
    int k,l,ans;
};
priority_queue < node,vector<node>,greater<node> > q;

bool operator >(const node &a,const node &b){
    return a.ans>b.ans;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",z+i);
        zy[i]=1;
    }
    sort(z+1,z+1+n);
    for(int i=1;i<=n;i++){
        scanf("%d",y+i);
        q.push((node){i,zy[i],z[i]+y[zy[i]]});
    }
    while(n--){
        printf("%d ",q.top().ans);
        int w=q.top().k;
        zy[w]++;
        q.pop();
        q.push((node){w,zy[w],z[w]+y[zy[w]]});
    }
    return 0;
}

emmmm
不要问我为什么变量名老是用z和y(我才不会告诉你zy是一个人名字的缩写呢)

 

posted @ 2019-07-02 21:23  喵呜,颜儿ღ  阅读(104)  评论(0编辑  收藏  举报