斜率dp
#include <STDIO.H>
#include <STRING.H>
#include <algorithm>
using namespace std;
const int MAXN = 10005;
const int MAXM = 5005;
// 斜率DP
/*
dp[i][x] = min(dp[j][x-1] + (a[i]-a[j+1])^2) x-1<=j<i
*/
int dp[MAXN][MAXM];
int a[MAXN];
int q[MAXN];
int n, m;
int getDP(int i, int j, int x)
{
return dp[j][x-1] + (a[i]-a[j+1])*(a[i]-a[j+1]);
}
int getUP(int k, int j, int x)
{
return dp[j][x-1]-dp[k][x-1] + a[j+1]*a[j+1] - a[k+1]*a[k+1];
}
int getDOWN(int k, int j)
{
return 2*(a[j+1] - a[k+1]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int i, x, cs = 0, t;
int head, tail;
scanf("%d", &t);
while ( t--)
{
scanf("%d%d", &n, &m);
printf("Case %d: ", ++cs);
for (i = 1; i<= n; i++)
scanf("%d", a+i);
sort(a+1, a+n+1);
for (i = 1; i<= n; ++i)
{
dp[i][1] = (a[i]-a[1])*(a[i]-a[1]);
}
for (x = 2; x<=m; x++)
{
head = tail = 0;
q[tail++] = x-1;
for (i = x; i<=n; ++i)
{
while (tail-head>1 && getUP(q[head],q[head+1],x)<=a[i]*getDOWN(q[head],q[head+1]))
head++;
dp[i][x] = getDP(i,q[head],x);
while (tail-head>1 && getUP(q[tail-2],q[tail-1],x)*getDOWN(q[tail-1],i)
>= getUP(q[tail-1],i,x)*getDOWN(q[tail-2],q[tail-1]))
tail--;
q[tail++] = i;
}
}
printf("%d\n", dp[n][m]);
}
return 0;
}