luogu1631 序列合并
2024-08-31 04:25:30
题目大意
有两个序列A,B,在A和B中各取一个数相加能得到$n^2$个和。求出这些和前n小的数字。
题解
首先这道题不可以用自己想的什么A序列B序列各两个指针的自己发明的模拟算法,用这样的算法只能是绝路一条。
此题入手点在于优化暴力。暴力算法是枚举所有的$A_i+B_j$,排个序,然后一个个输出。我们优化之处便是如何动态枚举$A_i,B_j$。
此时我曾想对两个数组都动态,这样想就走到了死胡同。
我们可以让A不动态,B动态,也就是优先队列里储存的数对里包含所有的$A_i$,但每个$A_I$只对应一个$B_j$。每次出队时,将$A_i$对应的$B_j$的j++再推入队列中。这样便有解了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; const int MAX_N = 100010, INF = 0x3f3f3f3f;
int A[MAX_N], B[MAX_N]; struct Element
{
int AId, BId; Element(int aId, int bId):AId(aId), BId(bId){} bool operator < (const Element a) const
{
return A[AId] + B[BId] > A[a.AId] + B[a.BId];
}
};
priority_queue<Element> q; int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", A + i);
for (int i = 1; i <= n; i++)
scanf("%d", B + i);
sort(A + 1, A + n + 1);
sort(B + 1, B + n + 1);
for (int i = 1; i <= n; i++)
q.push(Element(i, 1));
for (int i = 1; i <= n; i++)
{
Element cur = q.top();
q.pop();
printf("%d ", A[cur.AId] + B[cur.BId]);
if (cur.BId < n)
{
cur.BId++;
q.push(cur);
}
}
return 0;
}
最新文章
- 模拟搭建Web项目的真实运行环境(五)
- 关于MVC4.0中@Styles.Render用法与详解
- C++11:新式的字符串字面常量(String Literal)
- 重载Python FTP_TLS 实现Implicit FTP Over TLS方式下载文件
- Asp.net使用代码修改配置文件的节点值
- DOM_05之DOM、BOM常用对象
- 求最长回文子串 - leetcode 5. Longest Palindromic Substring
- 一起学HTML基础-利用CSS和JavaScript制作一个切换图片的网页
- openstack(liberty): devstack之screen
- linux 从命令行自动识别文件并将其打开的命令
- Mac系统Finder访问资源库文件夹
- apache开源项目--log4j
- ios开发应用内实现多语言自由切换
- 得到Android keystore签名的命令方法
- python面向对象的三大特征
- 对 Service中sqlsession对象的优化
- [leetcode 12] Inter to Roman
- docker镜像基本操作一
- Jmeter入门--参数化、集合点
- Java Web开发基础(3)-JSTL