题目:https://www.luogu.org/problemnew/show/P1631
一看题面,暴力选手,先打暴力。
非常简单的暴力,不加优化。
代码:
#include<bits/stdc++.h> #define rr(x) scanf("%d",&x) #define pp(x) printf("%d ",x) using namespace std; const int maxn=100001; int a[maxn],b[maxn]; priority_queue<int> q; int n; int main() { rr(n); for(int i=1;i<=n;i++){ rr(a[i]); } for(int i=1;i<=n;i++){ rr(b[i]); for(int j=1;j<=n;j++) q.push(-(a[j]+b[i])); } for(int i=1;i<=n;i++){ pp(-q.top()); q.pop(); } return 0; }
果然TLE了,过了60分,还不少。
不优化这个傻子算法了,开始想正解(看题解)。
果然洛谷神犇们还是没有让我失望,还是发现了理解的题解。
第一,由于是有序的,所以a[1]一定是有最优解的,所以,将所有的b和a[1]求和,入堆。
小根堆里用pair<int,int>,第一个int为值,第二个int为b的下标。
为了避免重复,定义to[i]为与b[i]结合的a的下标,效果后面会见到。
(rr是define的读入)
for(int i=1;i<=n;i++){ rr(b[i]);to[i]=1; q.push(make_pair(a[1]+b[i],i)); }
然后就是最后的答案,每次取出值之后,取出b的下标,依照to数组,给a的下标++,再次入堆。
全部代码如下:
#include<bits/stdc++.h> #define rr(x) scanf("%d",&x) #define pp(x) printf("%d ",x) using namespace std; const int maxn=100001; int a[maxn],b[maxn],to[maxn]; priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q; int n; int main() { rr(n); for(int i=1;i<=n;i++){ rr(a[i]); } for(int i=1;i<=n;i++){ rr(b[i]);to[i]=1; q.push(make_pair(a[1]+b[i],i)); } while(n--){ pp(q.top().first); int k=q.top().second; q.pop(); q.push(make_pair(a[++to[k]]+b[k],k)); } return 0; }