設序列 a1,a2,a3,a4,...,an 的平均值爲 x,權值和爲 tot,方差 S=ni=1∑n(ai−x)2
乘上 n2 得到:S=ni=1∑n(m∗ai−tot)2
統計分子部分,最後再除以 n。
題目轉化過來就是將 n 個數分成 m 段,使得最後 S 儘可能小。
每一段對 S 的分子部分的貢獻不難計算,考慮 dp,dp[i][j] 表示前 i 個數分成 j 段對 S 的最小貢獻
,答案顯然爲 dp[n][m]
轉移方程:dp[i][t]=j=1mini(dp[j][t−1]+(m∗(sum[i]−sum[j])−tot)2)
注意初值,對所有的 i<j,dp[i][j]=inf
直接做的複雜度是 n2m,考慮優化,將式子展開可以得到:
dp[i][t]=j=1mini(dp[j][t−1]+m2∗sum[i]2+m2∗sum[j]2−2m2∗sum[i]∗sum[j]+tot2−2m∗tot∗sum[i]+2∗m∗tot∗sum[j])
出現了 2m2∗sum[i]∗sum[j],考慮斜率優化,斜率爲 2m∗sum[i] (移項後的斜率),斜率單調遞增,要求 dp[i][t] 最小值,維護下凸包。
設 j>k,在 j 點比在 k 點轉移更優,則滿足 :
dp[j][t−1]+m2∗sum[i]2+m2∗sum[j]2−2m2∗sum[i]∗sum[j]+tot2−2m∗tot∗sum[i]+2∗m∗tot∗sum[j] <
dp[k][t−1]+m2∗sum[i]2+m2∗sum[k]2−2m2∗sum[i]∗sum[k]+tot2−2m∗tot∗sum[i]+2∗m∗tot∗sum[k]
式子非常長,後面一段就是把 j 換成 k,消掉相同的並進行移項化簡,最後可以得到:
令 c[i][t]=dp[i][t]+m2∗sum[i]2+2m∗tot∗sum[i]
代入得:sum[j]−sum[t]c[j][t−1]−c[k][t−1]<2m∗sum[i]
用單調隊列維護 sum[j]−sum[t]c[j][t−1]−c[k][t−1] 單增,根據決策單調性尋找最優轉移點,複雜度降爲 O(n∗m)
對第二維可以進行滾動,最後答案要記得除以 m。
代碼:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e3 + 10;
typedef long long ll;
const ll inf = 1e17;
int n,N;
ll sum[maxn],dp[maxn],tp[maxn],c[maxn],m[5],tot;
int q[maxn],front,rear;
ll calc(int x,int y) {
ll tmp = m[1] * (sum[x] - sum[y]) - tot;
return tp[y] + tmp * tmp;
}
int main() {
scanf("%d%d",&n,&m[1]);
for (int i = 2; i <= 4; i++)
m[i] = 1ll * m[i - 1] * m[1];
for (int i = 1,x; i <= n; i++)
scanf("%d",&sum[i]);
for (int i = 1; i <= n; i++)
sum[i] += sum[i - 1];
tot = sum[n];
for (int j = 1; j <= n; j++)
tp[j] = dp[j] = inf;
for (int t = 1; t <= m[1]; t++) {
front = rear = 0;
q[++rear] = t - 1;
for (int i = t; i <= n; i++) {
while (front + 1 < rear && calc(i,q[front + 1]) >= calc(i,q[front + 2]))
front++;
dp[i] = calc(i,q[front + 1]);
while (front + 1 < rear && (c[i] - c[q[rear]]) * (sum[q[rear]] - sum[q[rear - 1]])
<= (c[q[rear]] - c[q[rear - 1]]) * (sum[i] - sum[q[rear]]))
rear--;
q[++rear] = i;
}
for (int i = 0; i <= n; i++) {
tp[i] = dp[i];
c[i] = tp[i] + m[2] * sum[i] * sum[i] + 2 * m[1] * tot * sum[i];
dp[i] = inf;
}
}
printf("%lld\n",tp[n] / m[1]);
return 0;
}