【清北前紧急补课11】优先队列的正确使用方法
题目描述
有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到 N2N^2N2 个和,求这 N2N^2N2 个和中最小的N个。
输入输出格式
输入格式:第一行一个正整数N;
第二行N个整数 AiA_iAi , 满足 Ai≤Ai+1A_i\le A_{i+1}Ai≤Ai+1 且 Ai≤109A_i\le 10^9Ai≤109 ;
第三行N个整数 BiB_iBi , 满足 Bi≤Bi+1B_i\le B_{i+1}Bi≤Bi+1 且 Bi≤109B_i\le 10^9Bi≤109 .
【数据规模】
对于50%的数据中,满足1<=N<=1000;
对于100%的数据中,满足1<=N<=100000。
输出格式:输出仅一行,包含N个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。
输入输出样例
输入样例#1:
复制
3 2 6 6 1 4 8
输出样例#1: 复制
3 6 7
不难看出要使用优先队列,但是很明显如果循环到n会T那么几个点 那就理性来分析一下
如果我们i和j两个循环 分别枚举到√n 那么我们就能得到n个数据 但是很显然所求有的并不在n中 那么对于枚举到√n所获得的a[i]+a[j]<a[i']+a[j']必然要更新 更新的i' 和j'一定是一个在√n以内 另一个在√n到2*√n
因为已经排完序了 所以在2*√n到3*√n之间乃至更大所找的的用来更新的i'和j'显然不如之前的优
那么我们只要循环到2*√n就可以啦
上代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 priority_queue<int,vector<int>,greater<int> > q; 9 int main(){ 10 int n,a[100001],b[100001],s,to[100001]; 11 cin>>n; 12 for(int i=1;i<=n;i++){ 13 cin>>a[i]; 14 } 15 for(int i=1;i<=n;i++){ 16 cin>>b[i]; 17 } 18 sort(a+1,a+n+1); 19 sort(b+1,b+n+1); 20 21 for(int i=1;i<=2*sqrt(n);i++) 22 for(int j=1;j<=2*sqrt(n);j++){ 23 s=a[i]+b[j]; 24 q.push(s); 25 } 26 for(int i=1;i<=n;i++){ 27 cout<<q.top()<<" "; 28 q.pop(); 29 } 30 }