原题链接
解题思路
我们直接用贪心,将每家每户按疲劳值从大到小排序,那么他最大的可能疲劳值就是前 X 个疲劳值,加上前 X 个中最远的一个的距离*2。
当然,只这样操作的话,很轻松就会被hack了,比如一个在 1 位置的家庭疲劳值是 5,另一个在 4 位置的家庭疲劳值是 1。那么刚才的方法就没法用了。
所以我们可以考虑,在取到前 X 个疲劳值的时候,舍去最小的那一个值,也就是只剩下了 X-1 个,同时尝试用后面的某个距离更远的位置来替换我们舍去的那个值。
问题又来了,为什么只删去一个就可以了呢?
那是因为,如果后面有多个距离跳跃很远的位置,我们只要考虑最远的那个就可以了,只要有最远的距离,之前的只找最大的疲劳值就可以了。(还不理解的可以看看题目)
还有就是要用前缀和维护。
代码示例
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=100010;
int n;
int sum[maxn];
int f[maxn];
int b[maxn];
struct home{
int s;
int a;
}h[maxn];
bool cmp(const home &a,const home &b){
return a.a>b.a;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i].s;
for(int i=1;i<=n;i++) cin>>h[i].a;
sort(h+1,h+1+n,cmp);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+h[i].a;
for(int i=1;i<=n;i++) f[i]=max(f[i-1],2*h[i].s);
for(int i=n;i>=1;i--) b[i]=max(b[i+1],2*h[i].s+h[i].a);
for(int i=1;i<=n;i++) cout<<max(sum[i]+f[i],sum[i-1]+b[i])<<endl;
return 0;
}
|