做题记录2022.4.29洛谷P1631序列合并
可以很容易地想出暴力思路,但复杂度高达O(n2),所以必须优化
思路1:不难发现在a数组到i,b数组到j处,在它们前面的有i*j个,这i*j个数不可能比它大,所以只要在暴力枚举过程中判断i*j<=n即可。
最后只要对和排序,求出前n个。注意存放和的数组不能只有n个。
vector<int> sum;
for(int i=1; i<=n; i++) { for(int j=1; i*j<=n; j++) { sum.push_back(a[i]+b[j]); } } sort(sum.begin(),sum.end()); printf("%u",sum[0]); for(int i=1; i<n; i++) { printf(" %u",sum[i]); }
思路2:
暴力枚举的解法里,除了全部n2个弄完再排序之外,还可以使用一个优先队列。
由于要求最小的n个,所以这个队列的“容积”是n,一旦元素个数已达到n个,并且新的和小于队头,那么就先出队再将新的和入队。
注意到:当a到i,b到j时,如果新的和大于队头,那么后面再怎么遍历也不会小于队头了。所以可以这样优化:
for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { if(q.size()<n) { q.push(a[i]+b[j]); } else { if(a[i]+b[j]>q.top()) break; q.pop(); q.push(a[i]+b[j]); } } }

浙公网安备 33010602011771号