1245 最小的N个和

1245 最小的N个和

 

时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
 
 
 
 
题目描述 Description

有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个。

输入描述 Input Description

第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,
且Bi≤10^9

输出描述 Output Description

输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用
空格隔开。

样例输入 Sample Input

5

1 3 2 4 5
6 3 4 1 7

样例输出 Sample Output

2 3 4 4 5

数据范围及提示 Data Size & Hint

【数据规模】 对于 100%的数据,满足 1≤N≤100000。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm> 
 4 #define M 100010
 5 using namespace std;
 6 int a[M],b[M],heap[M],l=0;
 7 int put(int d)  //建立堆并维护 
 8 {
 9     heap[++l]=d;
10     int next,now=l;
11     while(now>1)
12     {
13         next=now/2;
14         if(heap[now]<=heap[next])break;
15         swap(heap[now],heap[next]);
16         now=next;
17     }
18 }
19 int get()  //删除堆顶元素 
20 {
21     int now,next;
22     heap[1]=heap[l--];
23     now=1;
24     while(now*2<=l)
25     {
26         next=now*2;
27         if(next<l&&heap[next]<heap[next+1])next++;
28         if(heap[now]>=heap[next])break;
29         swap(heap[now],heap[next]);
30         now=next;
31     }
32 }
33 int main()
34 {
35     int n;
36     scanf("%d",&n);
37     for(int i=1;i<=n;i++)
38         scanf("%d",&a[i]);
39     for(int i=1;i<=n;i++)
40         scanf("%d",&b[i]);
41     sort(a+1,a+n+1);  //排序 
42     sort(b+1,b+n+1);
43     heap[1]=(a[1]+b[1]);
44     for(int i=1;i<=n;++i)
45         put(a[1]+b[i]);  //初始化 
46     for(int i=2;i<=n;i++)
47     {
48         if(a[i]+b[1]>=heap[1])break;  //因为a,b,都是递增的,所以 a[i]+b[1]>=heap[1],以后的a会更大; 
49         for(int j=1;j<=n;j++)
50         {
51             if(a[i]+b[j]>=heap[1])continue; //因为a,b,都是递增的,所以 a[i]+b[j]>=heap[1],以后的b会更大; 
52             put(a[i]+b[j]);
53             get();  //删除最大的,留下n个数 
54         }
55     }    
56     sort(heap+1,heap+n+1);  //从小到大排序 
57     for(int i=1;i<=n;++i)  //输出 
58         printf("%d ",heap[i]);
59     return 0;
60 }
原文地址:https://www.cnblogs.com/mjtcn/p/6669852.html