分组
【问题描述】
小 w 是扬中的高一新生。俗话说新官上任三把火,作为班长,第一件事自然是要给全
班分座位。
这可不是一件简单的任务。大家都知道学霸是一种环境不友好型生物,所以在一个组里,
学霸会对同组的学渣造成巨大伤害。
具体来说,我们定义一个组的不和谐度为本组的最高成绩与最低成绩差的平方。如一个
组内的分数为 4 7 10 1,那么不和谐度为(10-1)^2=81。
现在,班主任给小 w 全班的成绩和要求分的组数,求全班所有小组的不和谐度的最小
值。
【输入格式】
多组测试数据。
每组测试数据,第一行两个整数 N,M,N 是全班人数,M 是组数
第二行 N 个整数表示全班成绩。
【输出格式】
每组测试数据,一行一个整数 S 表示全班所有小组的不和谐度的最小值。
答案保证在 32 位有符号整型范围内。
【输入输出样例】
输入:
2
3 2
1 2 4
4 2
4 7 10 1
输出:
【问题描述】
小 w 是扬中的高一新生。俗话说新官上任三把火,作为班长,第一件事自然是要给全
班分座位。
这可不是一件简单的任务。大家都知道学霸是一种环境不友好型生物,所以在一个组里,
学霸会对同组的学渣造成巨大伤害。
具体来说,我们定义一个组的不和谐度为本组的最高成绩与最低成绩差的平方。如一个
组内的分数为 4 7 10 1,那么不和谐度为(10-1)^2=81。
现在,班主任给小 w 全班的成绩和要求分的组数,求全班所有小组的不和谐度的最小
值。
【输入格式】
多组测试数据。
每组测试数据,第一行两个整数 N,M,N 是全班人数,M 是组数
第二行 N 个整数表示全班成绩。
【输出格式】
每组测试数据,一行一个整数 S 表示全班所有小组的不和谐度的最小值。
答案保证在 32 位有符号整型范围内。
【输入输出样例】
输入:
2
3 2
1 2 4
4 2
4 7 10 1
输出:
Case 1: 1
Case 2: 18
【数据范围】
对于 30%数据,M<=N<=10
对于 80%数据,M<=N<=100
对于 100%数据,M<=N<=5000
分析:斜率优化dp。
参考程序:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5100;
int f[maxn][2*maxn];
int a[2*maxn];
int n,m,head,tail;
int q[2*maxn];
int yy(int i,int j,int k){
return f[i-1][j]+a[j+1]*a[j+1]-(f[i-1][k]+a[k+1]*a[k+1]);
}
int xx(int j,int k){
return 2*(a[j+1]-a[k+1]);
}
int main(){
freopen("separate.in","r",stdin);
freopen("separate.out","w",stdout);
int T;
scanf("%d",&T);
int cnt=0;
while (T--){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for (int i=1;i<=n;i++){
f[1][i]=(a[i]-a[1])*(a[i]-a[1]);
}
for (int i=2;i<=m;i++){
head=tail=0;
q[tail++]=i-1;
for (int j=i;j<=n;j++){
while (head+1<tail && yy(i,q[head+1],q[head])<a[j]*xx(q[head+1],q[head]))
head++;
int k=q[head];
f[i][j]=f[i-1][k]+(a[j]-a[k+1])*(a[j]-a[k+1]);
while (head+1<tail && yy(i,j,q[tail-1])*xx(q[tail-1],q[tail-2])<=xx(j,q[tail-1])*yy(i,q[tail-1],q[tail-2]))
tail--;
q[tail++]=j;
}
}
printf("Case %d: %d\n",++cnt,f[m][n]);
}
return 0;
}