题目
题意: n个数分成m组,每组的花费是(max-min)^2,求最小花费;
先对所有数字的权值从小到大排序。
dp[i][j]:前 j 个数分成 i 组.
则转移方程为:dp[i][j]=dp[i-1][k]+(a[j]-a[k+1])^2.(0<=k<j)
把外层循环 i 看作定值,j 是状态变量,k 是决策变量。方程存在项 2 * a[j] * a[k+1],应考虑使用斜率优化。
变成方程 f[i]=f[j]+(a[i]-a[j+1]) ^ 2 (0<=j<i) 对方程进行移向,等号左边仅放与 j 有关的项,等号后边放 i , j乘积有关的项以及仅与 i 有关的项。
f[j] + a[j]^ 2=a[i] * (2 * a[j+1])+f[i]-a[i]^2;
f[j]:将前 j个数分成 d 组的花费 所以随着 j 变大 f[j]也增大
使用flag^1 进而采用滚动数组
#include<cstdio>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=1e4+5;
int a[N],dp[N][2],q[N],flag;//flag在这里用作滚动数组 每次修改分成第d+1组的 查询第d组需要用到d组的dp值 而更新则会乱套 所以采用滚动数组。
inline int getX(int i,int j){
return 2*a[j+1]-2*a[i+1];
}
inline