洛谷P1631 序列合并
Solution:
首先将
a
a
a与
b
b
b数组分别排序。
原理:对于每个
i
i
i,
a
i
+
b
i
<
=
a
i
+
b
i
+
1
<
=
.
.
<
=
a
i
+
b
N
a_i + b_i <= a_i + b_{i+1} <= .. <= a_i + b_N
ai+bi<=ai+bi+1<=..<=ai+bN
流程:
- 对于每个 i i i,初始化时将不等式打头的那个扔进优先队列。
- 取出最小值,弹出,然后将该不等式“所在位置”的后一位扔进优先队列。
如取出的值是 a 3 + b 5 a_3 + b_5 a3+b5,接下来应将 a 3 + b 6 a_3 + b_6 a3+b6扔进优先队列。
注意当取出的值为 a x + b x a_x + b_x ax+bx时,应将 a x + 1 + b x , a x + b x + 1 a_{x+1} + b_x,a_x + b_{x+1} ax+1+bx,ax+bx+1扔进优先队列。 - 重复步骤2,直到取出 N N N次。
code:
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 100007;
int N;
struct Node {
int x, y, sum; // A中元素的标号,B中元素的标号,两个标号对应的值之和
Node (int x = 0, int y = 0, int sum = 0) : x(x), y(y), sum(sum) {}
bool operator < (const Node h) const {return sum > h.sum;}
};
int A[MAXN], B[MAXN];
int tota[MAXN], totb[MAXN];
priority_queue <Node> Q;
int main() {
#ifdef test
freopen("test.txt", "r", stdin);
#endif
cin >> 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 + N + 1);
sort(B + 1, B + N + 1);
for(int i = 1; i <= N; i++) {
tota[i] = totb[i] = i;
Q.push(Node(i, i, A[i] + B[i]));
}
for(int i = 1; i <= N; i++) {
Node h = Q.top(); Q.pop();
int x = h.x, y = h.y;
printf("%d ", h.sum);
if(x < y)
if(tota[x] < N)
++tota[x], Q.push(Node(x, tota[x], A[x] + B[tota[x]]));
if(x == y) {
if(tota[x] < N)
++tota[x], Q.push(Node(x, tota[x], A[x] + B[tota[x]]));
if(totb[y] < N)
++totb[y], Q.push(Node(totb[y], y, B[y] + A[totb[y]]));
}
if(x > y)
if(totb[y] < N)
++totb[y], Q.push(Node(totb[y], y, B[y] + A[totb[y]]));
}
return 0;
}

浙公网安备 33010602011771号