斜率优化DP
T1
code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll f1(ll, ll, ll), f2(ll, ll);
bool xyl(ll a, ll b) { return a < b; }
const ll N = 10005, M = 5005;
int dp[M][N], num[N], n, m, z, Q[N];
int main()
{
scanf("%d", &z);
for (int i = 1; i <= z; i++)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]);
sort(num + 1, num + 1 + n, xyl);
ll l, r;
for (int i = 1; i <= n; i++)
dp[1][i] = (num[i] - num[1]) * (num[i] - num[1]);
for (int j = 2; j <= m; j++)
{
l = r = 1;
Q[r++] = j - 1;
for (int i = j; i <= n; i++)
{
while (l + 1 < r && f1(Q[l + 1], Q[l], j) <= f2(Q[l + 1], Q[l]) * num[i])
++l;
ll w = Q[l];
dp[j][i] = dp[j - 1][w] + (num[i] - num[w + 1]) * (num[i] - num[w + 1]);
while (l + 1 < r && f1(Q[r - 1], Q[r - 2], j) * f2(i, Q[r - 1]) >=
f2(Q[r - 1], Q[r - 2]) * f1(i, Q[r - 1], j))
--r;
Q[r++] = i;
}
}
printf("Case %d: %d\n", i, dp[m][n]);
}
return 0;
}
ll f1(ll a, ll b, ll j)
{
return dp[j - 1][a] - dp[j - 1][b] + num[a + 1] * num[a + 1] - num[b + 1] * num[b + 1];
}
ll f2(ll a, ll b) { return 2 * (num[a + 1] - num[b + 1]); }