有序表的最小和
【问题描述】
给出长度为n得有序表A和B,在A和B中各取一个元素,可以得到n^2个和,求这些和中最小的n个
【输入格式】
第一行包含一个整数n(n<=400000)
第二行与第三行分别n个整数,从小到大排列
【输入样例】
3
1 2 5
2 4 7
【输出样例】
3
4
5
【算法分析】
由题意知,
A[1]<=A[2]<=A[3]<=a[4]...
B[1]<=B[2]<=B[3]<=B[3]...
设C[a,b]=A[a]+B[b]
可知对于每一个a来说
C[a,1]<=C[a,2]<=C[a,3]...
此时C[a]构成一个数列
每一次生成的最小值必定是C[a](1<=a<=n)每个数列的头中最小的
例如
1 2 5
2 4 7
C[a,b]
a/b 1 2 3
1 3 5 8
2 4 6 9
3 7 9 12
第一个最小的数必定在3,4,7三数之间 为3,3去掉,此时c[1]表头为5
第二个最小的数必定在5,4,7三数之间 为4, 4去掉,此时c[2表头为6
第三个最小的数必定在5,6,9三数之间 为5, 5去掉,此时c[1]表头为8
【算法实现】
由此我们可以维护一个小根堆
开始时这个堆有n个元素,它们为每个表的头元素c[a,1](1<=a<=n)
每次取出小根堆的根元素并将该元素所在表的表头更新:其实并没有必要建表,只需修改该根元素的值为该表下一个值即可
维护堆,重复n次
【程序】
<span style="font-size:14px;">//2016-4-7
//Gods save princess!
//By Shui'bing ICEE
const
maxn=500000;//!!!!!
type
node=record
b,data:longint;
end;
var
heap:array[0..maxn] of node;
a,b:array[0..maxn] of longint;
i,n,l:longint;
procedure put(x,b:longint);
var
son,temp:longint;
begin
inc(l);
heap[l].b:=b;
heap[l].data:=x;
son:=l;
while (son<>1) and (heap[son div 2].data>heap[son].data) do
begin
temp:=heap[son div 2].data;
heap[son div 2].data:=heap[son].data;
heap[son].data:=temp;
temp:=heap[son div 2].b;
heap[son div 2].b:=heap[son].b;
heap[son].b:=temp;
end;
end;
function get:longint;
var
fa,son,temp:longint;
stop:boolean;
begin
get:=heap[1].data;
heap[1].data:=heap[1].data-b[heap[1].b]+b[heap[1].b+1];
inc(heap[1].b);
fa:=1;
stop:=false;
while (fa*2<=l) and (not stop) do
begin
if (fa*2+1>l) or (heap[fa*2].data<heap[fa*2+1].data)
then son:=fa*2
else son:=fa*2+1;
if heap[fa].data>heap[son].data
then begin
temp:=heap[fa].data;
heap[fa].data:=heap[son].data;
heap[son].data:=temp;
temp:=heap[fa].b;
heap[fa].b:=heap[son].b;
heap[son].b:=temp;
end
else stop:=true;
end;
end;
begin
read(n);
for i:=1 to n do
read(a[i]);
for i:=1 to n do
read(b[i]);
l:=0;
for i:=1 to n do
begin
put(a[i]+b[1],1);
end;
for i:=1 to n do
writeln(get);
end.</span>