序列合并(luogu 1631)题解
【问题描述】
有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到N^2个和,求这N^2个和中最小的N个。
【样例输入】
3
2 6 6
1 4 8
【样例输出】
3 6 7
【解题思路】
这道题目其实是一道裸的最小堆的题目,而且它给出了Ai<=A(i+1),Bi<=B(i+1),我们连排序都可以不用排,我们建一个堆为C,首先C中存放N个值,分别为A1+B1,A2+B1,...An+B1,然后我们将其建成一个小根堆,每一次取堆顶元素并维护,然后插入Ai+B(j+1)到堆中并维护,因此,我们需要一个记录类型来作为堆,该记录类型有着三个值,分别存储i,j和a[i]+b[j]的值,然后我们以a[i]+b[j]为关键字维护堆即可。
【代码实现】
1 type rec=record 2 jbh,data,ibh:longint; 3 end; 4 var n,i,j,n1,ii,jj:longint; 5 a,b:array[0..100010] of longint; 6 c:array[0..100010] of rec; 7 procedure sift(i,m:longint); 8 var k:longint; 9 begin 10 c[0]:=c[i]; 11 k:=i shl 1; 12 while k<=m do 13 begin 14 if (k<m)and(c[k].data<c[k+1].data) then 15 inc(k); 16 if c[0].data<c[k].data then 17 begin 18 c[i]:=c[k]; 19 i:=k; 20 k:=i shl 1; 21 end 22 else 23 k:=m+1; 24 end; 25 c[i]:=c[0]; 26 end; 27 procedure insert(k,ii,jj:longint); 28 var i:longint; 29 y:rec; 30 begin 31 inc(n1); 32 c[n1].data:=k; 33 c[n1].ibh:=ii; 34 c[n1].jbh:=jj; 35 i:=n1; 36 while (i shr 1>0)and(c[i shr 1].data>k) do 37 begin 38 y:=c[i]; 39 c[i]:=c[i shr 1]; 40 c[i shr 1]:=y; 41 i:=i shr 1; 42 end; 43 end; 44 procedure heapsort; 45 var j:longint; 46 y:rec; 47 begin 48 for j:=n shr 1 downto 1 do 49 sift(j,n); 50 for j:=n downto 2 do 51 begin 52 y:=c[1]; 53 c[1]:=c[j]; 54 c[j]:=y; 55 sift(1,j-1); 56 end; 57 end; 58 function deletemin:longint; 59 var i,pos:longint; 60 y:rec; 61 begin 62 i:=1; 63 deletemin:=c[1].data; 64 c[1]:=c[n1]; 65 dec(n1); 66 while i shl 1<=n1 do 67 begin 68 pos:=i shl 1; 69 if (pos<n1)and(c[pos+1].data<c[pos].data) then 70 inc(pos); 71 if c[i].data>c[pos].data then 72 begin 73 y:=c[i]; 74 c[i]:=c[pos]; 75 c[pos]:=y; 76 i:=pos; 77 end 78 else 79 break; 80 end; 81 end; 82 begin 83 readln(n); 84 for i:=1 to n do 85 read(a[i]); 86 for i:=1 to n do 87 read(b[i]); 88 for i:=1 to n do 89 begin 90 c[i].data:=a[i]+b[1]; 91 c[i].jbh:=1; 92 c[i].ibh:=i; 93 end; 94 heapsort; 95 n1:=n; 96 for i:=1 to n do 97 begin 98 ii:=c[1].ibh; 99 jj:=c[1].jbh; 100 write(deletemin,' '); 101 inc(jj); 102 insert(a[ii]+b[jj],ii,jj); 103 end; 104 end.