题解:P12052 [THUPC 2025 决赛] 图,距离,最优化
fish_love_cat · · 题解
首先答案与给出的节点顺序无关,考虑降序排序。
我们猜想
证明:
如果说
于是最优情况下
进一步猜想
证明:
如果说
于是最优情况下
现在可以直接当序列来做了。
于是想到把最大值放两头贪心构造序列,但是这连样例都过不了。
为了最大化距离,我们对于大的数字放在左右两头显然是比放中间优秀的。
发现只用分讨两种情况,所以我们大力 dp 即可。
注意极小值要足够小,不然会出现这种东西。
答案很大要开 long long。
多测清空。
做完了。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[305],b[2][600005];
bool cmp(int x,int y){
return x>y;
}
void solve(){
int n;
cin>>n;
a[0]=0;//多测清空多测清空多测清空多测清空多测清空
for(int i=1;i<=n;i++)
cin>>a[i],a[0]+=a[i];
sort(a+1,a+1+n,cmp);
for(int i=0;i<=a[0];i++)
b[0][i]=b[1][i]=-114514;
b[0][0]=0;
b[1][0]=0;
int m=0;
for(int i=1;i<=n;i++){
m+=a[i];
for(int j=0;j<=m;j++){
int ret=m-j-a[i];
ret=b[(i+1)&1][j]+ret*(a[0]-ret);
if(j>=a[i])ret=max(ret,b[(i+1)&1][j-a[i]]+j*(a[0]-j));
b[(i)&1][j]=ret;
}
}
int ans=0;
for(int i=0;i<=a[0];i++)
ans=max(ans,b[n&1][i]);
cout<<ans<<'\n';
}
signed main(){
int t;
cin>>t;
while(t--)solve();
return 0;
}