zoukankan      html  css  js  c++  java
  • 【洛谷P1631】序列合并【堆】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P1631
    有两个长度都是nn的序列aabb,在aabb中各取一个数相加可以得到n2n^2个和,求这n2n^2个和中最小的nn个。


    题外话:

    AC500祭color{red} exttt{AC500祭}在这里插入图片描述

    我的正确率是真的低qwq


    思路:

    由于题目中说a,ba,b都是单调递增的。所以就可以不考虑排序。
    单调递增同时特满足了
    a[x]+b[1]<a[x]+b[2]<...<a[x]+a[n](x[1,n])a[x]+b[1]<a[x]+b[2]<...<a[x]+a[n](xin [1,n])

    所以我们每次只要维护nn个数的最小值就可以了(分别是a[1]+b[k1],a[2]+b[k2],...,a[n]+b[kn]a[1]+b[k_1],a[2]+b[k_2],...,a[n]+b[k_n],其中kik_i表示ii所维护完的bb数组指针)
    求最小值可以考虑维护一个小根堆。每一个元素维护一个三元组(val,x,k)(val,x,k),表示这个a[x]+b[k]a[x]+b[k]的值。
    如果(vali,xi,ki)(val_i,x_i,k_i)是堆里的最小值,那么就输出valival_i,弹出,并插入(a[xi]+b[ki+1],xi,ki+1)(a[x_i]+b[k_i+1],x_i,k_i+1)
    nn次上述方法即可。
    时间复杂度O(nlogn)O(nlog n)


    代码:

    #include <queue>
    #include <cstdio>
    #define mp make_pair
    using namespace std;
    
    const int N=100010;
    int n,a[N],b[N];
    priority_queue<pair<int,pair<int,int> > > q;  //pair套pair最为致命(三元组)
    
    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]);
    	for (int i=1;i<=n;i++)
    		q.push(mp(-a[i]-b[1],mp(i,1)));  //插入初始值
    	for (int i=1;i<=n;i++)
    	{
    		printf("%d ",-q.top().first);
    		int x=q.top().second.first,y=q.top().second.second;
    		q.pop();
    		q.push(mp(-a[x]-b[y+1],mp(x,y+1)));
    	}
    	return 0;
    }
    
  • 相关阅读:
    裸裸的spfa~嘿嘿嘿!
    睡前1小时数学系列之-整除
    拓扑排序1.奖金
    拓扑排序
    SCU 1095运送物资(最短路)
    POJ1158 城市交通Traffic lights IOI 1999 (最短路)
    POI0109 POD (最短路)
    HN0I2000最优乘车 (最短路变形)
    FOJ1205 小鼠迷宫问题 (BFD+递推)
    CJOI 05新年好 (最短路+枚举)
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998149.html
Copyright © 2011-2022 走看看