做题记录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]);
        }
    }
}

 

 


 

posted @ 2022-04-29 16:45  m0_51303687  阅读(57)  评论(0)    收藏  举报