本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
题目链接
题目
题目大意
有 块砖,编号从 到 。第 块砖的重量为 。初始有 3 个空袋子分别以 标号。
Pak Chanek 把 块砖分别放进 3 个空袋子里,需要保证每个袋子里至少有一块砖。Bu Dengklek 从 3 三个袋子里分别取出一块砖,记从第 1 个袋子里取出来的砖的重量为 ,从第 2 个袋子里取出来的砖的重量为 ,从第 3 个袋子里取出来的砖的重量为 ,则得分为 。
Bu Dengklek 想最小化得分,如果 Pak Chanek 以最佳方式往三个袋子里放砖,最终可能的最大分数是多少?
思路
如果我们把所有砖的重量排序并去重,将排序去重后的重量记为 ,则:
- 如果 ,则答案为 0。
- 如果 ,则答案为 。即我们可以把出现次数更多的砖放进 1,3 袋子里,另一种砖放在第二个袋子里。
接下来我们讨论 的情况。
如果我们把 放在第一个袋子里, 放在第三个袋子里,其他元素放在中间,则最终的答案就是 。显然以下两种情况算出来的答案会更大:
前者的答案是 ,即将 放在第 1 个袋子里, 放在第 2 个袋子里,其他元素放在最后。后者的答案是 ,即将 放在第 2 个袋子里, 放在第 3 个袋子里,其他元素放在第 1 个袋子里。
这样是否就能取得最优解呢?如果把 放在第 1 个袋子里,把 到 都放在中间,把 到 放在最后,就能取到答案 。如果 对答案造成的正面影响大于 比 小造成的负面影响, 就是更优的解。第二种情况与之类似。
所以我们需要枚举每块砖作为拐点的情况,取最优解输出答案。
代码
#include <bits/stdc++.h>
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
int n,m,k;
LL a[N],b[N];
int solve()
{
scanf("%d",&n);
LL ans=0;
for (int i=1;i<=n;++i) scanf("%lld",&a[i]);
sort(a+1,a+1+n);
m=0;
for (int i=1;i<=n;++i)
if (a[i]!=a[i-1]) b[++m]=a[i];
if (m==1) return printf("0\n"),0;
if (m==2) return printf("%lld\n",(b[2]-b[1])*2),0;
ans=b[m]-b[1];
for (int i=1;i<m;++i)
ans=max(ans,b[m]-b[i]+b[i+1]-b[i]);
for (int i=m;i>1;--i)
ans=max(ans,b[i]-b[1]+b[i]-b[i-1]);
printf("%lld\n",ans);
return 0;
}
int main()
{
int T=1;
for (scanf("%d",&T);T--;) solve();
return 0;
}