思路:很普通的斜率dp
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define Maxn 10010 #define LL int using namespace std; LL dp[Maxn][2],num[Maxn]; int que[Maxn*10]; inline LL getleft(int x,int j,int k) {return dp[j][x]+num[j+1]*num[j+1]-(dp[k][x]+num[k+1]*num[k+1]); } inline LL getright(int j,int k) {return 2*(num[j+1]-num[k+1]); } int main() {int n,m,i,j,head,rear,t,Ca=0;int now,pre;scanf("%d",&t);while(t--){memset(dp,0,sizeof(dp));scanf("%d%d",&n,&m);for(i=1;i<=n;i++)scanf("%d",num+i);sort(num+1,num+n+1);now=1,pre=0;for(i=1;i<=n;i++)dp[i][now]=(num[i]-num[1])*(num[i]-num[1]);for(j=1;j<m;j++){head=1,rear=0;que[++rear]=j-1;now=!now;pre=!pre;for(i=j;i<=n;i++){while(head<rear&&getleft(pre,que[head+1],que[head])<getright(que[head+1],que[head])*num[i])head++;dp[i][now]=dp[que[head]][pre]+(num[i]-num[que[head]+1])*(num[i]-num[que[head]+1]);while(head<rear&&getleft(pre,i,que[rear])*getright(que[rear],que[rear-1])<=getleft(pre,que[rear],que[rear-1])*getright(i,que[rear]))rear--;que[++rear]=i;}}printf("Case %d: %d\n",++Ca,dp[n][now]);}return 0; }