1. 程式人生 > >洛谷 P1631 序列合併

洛谷 P1631 序列合併

題目:序列合併

首先,把A和B兩個序列分別從小到大排序,變成兩個有序佇列。
這樣,從A和B中各任取一個數相加得到N2個和,可以把這些和看成形成了n個有序表/佇列:
A[1]+B[1] <= A[1]+B[2] <=<= A[1]+B[N]
A[2]+B[1] <= A[2]+B[2] <=<= A[2]+B[N]
……
A[N]+B[1] <= A[N]+B[2] <=<= A[N]+B[N]
接下來,就相當於要將這N個有序佇列進行合併排序:
首先,將這N個佇列中的第一個元素放入一個堆中;
然後;每次取出堆中的最小值。若這個最小值來自於第k個佇列,那麼,就將第k個佇列的下一個元素放入堆中。
時間複雜度:O
(NlogN)

程式碼:

#include<bits/stdc++.h>
using namespace std;

#define maxn 100000
#define read(x) scanf("%d",&x)
#define ll long long

struct Pair {
	int x,y;
	Pair(){}
	Pair(int xx,int yy) {x=xx,y=yy;}
	bool operator < (const Pair& oth) const {
		return x>oth.x;
	}
};

int n;
int a[maxn+
5],b[maxn+5]; priority_queue<Pair> que; int t[maxn+5]; int main() { read(n); for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<=n;i++) read(b[i]); for(int i=1;i<=n;i++) { que.push(Pair(a[1]+b[i],i)); t[i]=1; } for(int i=1;i<=n;i++) { Pair h=que.top();que.pop(); if(
t[h.y]!=n) { t[h.y]++; que.push(Pair(a[t[h.y]]+b[h.y],h.y)); } printf("%d ",h.x); } return 0; }