标签:space 子集 cin 最小 while for using scan printf
//将含有N个元素的一个集合分成M个子集,使得每个子集的最大值与最小值平方差的和最小。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e4+50;
const int maxm = 5e3+50;
ll dp[maxn][maxm] ,v[maxn] ;
int n ,m ;
int q[maxn] ,r,l ;
ll getdp(int i,int j,int k) {
return dp[k][j-1] + (v[i] - v[k + 1]) * (v[i] - v[k + 1]);
}
ll y(int j,int k,int q) {
return dp[k][j-1] + v[k + 1] * v[k + 1] - (dp[q][j-1] + v[q + 1] * v[q + 1]);
}
ll x(int k,int q) {
return 2 * ( v[k + 1] - v[q + 1] );
}
int main() {
int t ,ncase = 1 ;
cin>>t;
while(t--) {
scanf("%d %d",&n ,&m );
for (int i = 1; i<=n; i++)
scanf("%lld",&v[i] );
sort(v + 1 ,v + n + 1 );
for (int i = 1; i<=n; i++)
dp[i][1] = (v[i] - v[1]) * (v[i] - v[1]);
for (int i = 2; i<=m; i++) {
l = r = 0;
q[0] = i - 1;
for (int j = i; j<=n; j++) {
while(l < r && y(i ,q[l+1] ,q[l]) < x(q[l+1] ,q[l]) * v[j] )
l ++;
dp[j][i] = getdp(j ,i ,q[l] );
while(l < r && y(i ,q[r] ,q[r-1]) * x(j ,q[r]) >= y(i ,j ,q[r]) * x(q[r] ,q[r-1]) )
r --;
q[++r] = j;
}
}
printf("Case %d: ",ncase++);
printf("%lld\n",dp[n][m]);
}
return 0;
}
标签:space 子集 cin 最小 while for using scan printf
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12519135.html