题意:
给定n个石头和三个空背包,将n个石头放入三个背包中。从三个背包中拿出三个石头,假设冲三个包中拿出的石头的质量为 a,b,c ,最终的分数为 |a−b|+|b−c| ,取石头的人会最小化这个值,请问如何分配石头可以使得最终的分数最大。
思路:
贪心题,考虑贡献
先把a数组排个序
我们去考虑|a−b|+|b−c|的几何意义,其贡献就是b离a和c的距离之和
因为取石头的人会最小化这个值,因此他会尽可能让a和c作为极值,b作为中间值,此时取到最小,但是我们在放石头的时候想要使这个值尽可能大,也就是说我们要让取石子的人尽可能取不到这个值,即背包B的值要不是a数组的前缀,要不是a数组的后缀,至于前缀到哪里,这就需要枚举了
考虑前缀的话,取石子的人为了最小化贡献,会选前缀的最大值,即a[i],然后对于第二个背包会选a[i+1],对于第三个背包,会选第三个背包的最小值,因此我们在分配石子的时候应该要让第三个背包的最小值最大,因此第三个背包直接取a[n]即可
同理,如果考虑后缀的话,取石子的人为了最小化贡献,会选后缀的最小值,即a[i],然后对于第二个背包,会选a[i-1],对于第三个背包,选a[1]
Code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=2e5+10;
int n,ans=-1;
int a[mxn];
void solve(){
ans=-1;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
for(int i=1;i<=n-1;i++) ans=max(ans,a[i+1]-a[i]+a[n]-a[i]);
for(int i=n;i>=2;i--) ans=max(ans,a[i]-a[i-1]+a[i]-a[1]);
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T;
cin>>T;
while(T--)solve();
return 0;
}
总结:
做思维题多考虑几何意义,使思维变得清晰