CF1656F Parametric MST 题解
为了便于解题,先对
首先,根据定义可以得出总价值的表达式:
接着,我们需要发现一个比较重要的性质:
也就是说,如果固定一个
现在来考虑一下无解的情况:
-
如果
,那么除了 以外的所有结点向 连边,有可以发现,
是关于 的一次函数。由于满足 ,所以如果一次项系数 ,那么当 时 ,该函数不存在最大值。 -
如果
,同理有:类似的,如果
,当 时, ,不存在最大值。
综上,如果 INF
即可。
现在来考虑有解时如何寻找解。这时我们就需要引入一个新的性质:
-
如果
能取到最大值, 的值一定是 数组中的其中一个元素的值。证明:
容易得知当
取到最值时, (否则函数不收敛)。当
时,最优的连边方式之一是将所有的 向结点 连边(因为这些 满足 ),其他结点向 连边。所以我们可以得到 的表达式:(注意到这里
和 之间的边仅仅被连了一次,所以最终不用考虑重边的影响。)在这里因为
确定,所以 还是关于 的一次函数,最值必然在 或 时取到。命题得证。
接下来只用枚举
中间那一些求和的式子可以使用前缀和维护。
放代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
main(){
ios::sync_with_stdio(false);
int t; cin>>t;
while(t--){
int n,c=LLONG_MIN; cin>>n;
vector<int> a(n),s;
for(auto &i:a)cin>>i;
sort(a.begin(),a.end()); // 排序
partial_sum(a.begin(),a.end(),back_inserter(s)); // 做前缀和
if(a[0]*(n-2)+s[n-1]>0||a[n-1]*(n-2)+s[n-1]<0)cout<<"INF\n"; // 无解情况
else{
for(int i=0;i<n;i++)
c=max(c,a[0]*(s[n-1]-s[i])-a[i]*(a[0]*(n-i-1)+s[n-1]-s[i])+a[n-1]*(s[i]-s[0])-a[i]*(a[n-1]*i+s[i]-s[0]));
// 带入表达式计算
cout<<c<<endl;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理