题面描述
思路
方法一
方差
s 2 = ∑ i = 1 k ( v i − v ˉ ) 2 k s^2=\frac{\sum_{i=1}^k(v_i-\bar{v})^2}{k} s2=k∑i=1k(vi−vˉ)2
v ˉ = ∑ i = 1 k v i k \bar{v}=\frac{\sum_{i=1}^k v_i}{k} vˉ=k∑i=1kvi
s 2 = ∑ i = 1 k ( 1 k ∑ j = 1 k v j − v i ) 2 k s^2=\frac{\sum_{i=1}^k(\frac{1}{k}\sum_{j=1}^k v_j-v_i)^2}{k} s2=k∑i=1k(k1∑j=1kvj−vi)2
s 2 = ∑ i = 1 k v i 2 + k ∗ ( ∑ j = 1 k v j k ) 2 − 2 ∗ ( ∑ j = 1 k v j ) 2 k k s^2=\frac {\sum_{i=1}^k v_i^2+k*(\frac{\sum_{j=1}^kv_j}{k})^2-2*\frac{(\sum_{j=1}^kv_j)^2}{k}}{k} s2=k∑i=1kvi2+k∗(k∑j=1kvj)2−2∗k(∑j=1kvj)2
s 2 = ∑ i = 1 k v i 2 + ( ∑ j = 1 k v j ) 2 k − 2 ∗ ( ∑ j = 1 k v j ) 2 k k s^2=\frac {\sum_{i=1}^k {v_i}^2+\frac{(\sum_{j=1}^kv_j)^2}{k}-2*\frac{(\sum_{j=1}^kv_j)^2}{k}}{k} s2=k∑i=1kvi2+k(∑j=1kvj)2−2∗k(∑j=1kvj)2
s 2 k 2 = k ∗ ∑ i = 1 k v i 2 − ( ∑ i = 1 k v i ) 2 s^2k^2=k*\sum_{i=1}^k{v_i}^2-(\sum_{i=1}^kv_i)^2 s2k2=k∗i=1∑kvi2−(i=1∑kvi)2
状态转移方程
最终答案为 s 2 m 2 = m ∗ ∑ i = 1 m v i 2 − ( ∑ i = 1 m v i ) 2 s^2m^2=m*\sum_{i=1}^m{v_i}^2-(\sum_{i=1}^mv_i)^2 s2m2=m∗∑i=1mvi2−(∑i=1mvi)2
( ∑ i = 1 m v i ) 2 (\sum_{i=1}^mv_i)^2 (∑i=1mvi)2是一个定值。
只需计算 ∑ i = 1 m v i 2 \sum_{i=1}^m{v_i}^2 i=1∑mvi2
设 s s s为长度前缀和,则
F i , p + 1 = min ( F j , p + ( s i − s j ) 2 ) ( i > j ) F_{i,p+1}=\min(F_{j,p}+(s_i-s_j)^2)(i>j) Fi,p+1=min(Fj,p+(si−sj)2)(i>j)
决策单调性
F j , p + ( s i − s j ) 2 ≥ F k , p + ( s i − s k ) 2 F_{j,p}+(s_i-s_j)^2\ge F_{k,p}+(s_i-s_k)^2 Fj,p+(si−sj)2≥Fk,p+(si−sk)2
对于未来状态 t t t,证明:
F j , p + ( s t − s j ) 2 ≥ F k , p + ( s t − s k ) 2 ∗ m F_{j,p}+(s_t-s_j)^2\ge F_{k,p}+(s_t-s_k)^2*m Fj,p+(st−sj)2≥Fk,p+(st−sk)2∗m
s t = s i + v a l ( v a l > 0 ) s_t=s_i+val(val>0) st=si+val(val>0)
只需证明:
− s j ≥ − s k -s_j\ge-s_k −sj≥−sk
s j < s k s_j< s_k sj<sk,证毕。
踢队头
F j , p + ( s i − s j ) 2 ≥ F k , p + ( s i − s k ) 2 F_{j,p}+(s_i-s_j)^2\ge F_{k,p}+(s_i-s_k)^2 Fj,p+(si−sj)2≥Fk,p+(si−sk)2
F j , p − 2 ∗ s i ∗ s j + s j 2 ≥ F k , p − 2 ∗ s i ∗ s k + s k 2 F_{j,p}-2*s_i*s_j+{s_j}^2\ge F_{k,p}-2*s_i*s_k+{s_k}^2 Fj,p−2∗si∗sj+sj2≥Fk,p−2∗si∗sk+sk2
F k , p − F j , p + s k 2 − s j 2 ≤ 2 ∗ s i F_{k,p}-F_{j,p}+{s_k}^2-{s_j}^2\le2*s_i Fk,p−Fj,p+sk2−sj2≤2∗si
c a l c ( j , k ) = F k , p − F j , p + s k 2 − s j 2 s k − s j ≤ 2 ∗ s i calc(j,k)=\frac{F_{k,p}-F_{j,p}+{s_k}^2-{s_j}^2}{s_k-s_j}\le 2*s_i calc(j,k)=sk−sjFk,p−Fj,p+sk2−sj2≤2∗si
k k k优于 j j j
即
c a l c ( q h e a d , q h e a d + 1 ) ≤ 2 ∗ s i calc(q_{head},q_{head+1})\le 2*s_i calc(qhead,qhead+1)≤2∗si
q h e a d + 1 q_{head+1} qhead+1优于 q h e a d q_{head} qhead,踢去 h e a d head head
维护一个 c a l c ( q h e a d , q h e a d + 1 ) ≥ 2 ∗ s i calc(q_{head},q_{head+1})\ge 2*s_i calc(qhead,qhead+1)≥2∗si队列
同时我们可以发现, c a l c ( q h e a d , q h e a d + 1 ) calc(q_{head},q_{head+1}) calc(qhead,qhead+1)随 2 ∗ s i 2*s_i 2∗si的增大, h e a d head head不断增大,而不断增大。
因此,队列维护的应该是一个下凸壳。
踢队尾
由于维护一个下凸壳,
所以
c a l c ( q t a i l − 1 , q t a i l ) ≤ c a l c ( q t a i l , i − m ) calc(q_{tail-1},q_{tail})\le calc(q_{tail},i-m) calc(qtail−1,qtail)≤calc(qtail,i−m)
反之,
当
c a l c ( q t a i l − 1 , q t a i l ) ≥ c a l c ( q t a i l , i − m ) calc(q_{tail-1},q_{tail})\ge calc(q_{tail},i-m) calc(qtail−1,qtail)≥calc(qtail,i−m)
踢去队尾。
方法一 code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define gc getchar()
#define ll long long
using namespace std;
const int N=3e3+10;
template<class orz>
inline void qr(orz &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
void qw(ll x)
{
if(x<0)x=-x,putchar('-');
if(x/10)qw(x/10);
putchar(x%10+48);
}
ll f[N],g[N],ave;int s[N];
inline double calc(int j,int k)
{
return (double)(g[k]-g[j]+s[k]*s[k]-s[j]*s[j])/(s[k]-s[j]);
}
int q[N],l,r;
int main()
{
int n,m;qr(n);qr(m);
for(int i=1;i<=n;i++)qr(s[i]),s[i]+=s[i-1];
for(int i=1;i<=n;i++)f[i]=s[i]*s[i];
for(int j=2;j<=m;j++)
{
memcpy(g,f,n<<3);l=1;r=1;q[1]=j-1;
for(int i=j;i<=n;i++)
{
while(l<r&&calc(q[l],q[l+1])<=2.0*s[i])++l;
while(l<r&&calc(q[r],i)<=calc(q[r-1],q[r]))--r;
q[++r]=i;f[i]=g[q[l]]+(s[i]-s[q[l]])*(s[i]-s[q[l]]);
}
}
qw(f[n]*m-s[n]*s[n]);
return 0;
}
方法二
设 s s s为长度前缀和
仔细观察发现,貌似一天所走的路(从 j + 1 j+1 j+1走到 i i i)对最终答案的贡献为:
( s i − s j − a v e ) 2 ∗ m (s_i-s_j-ave)^2*m (si−sj−ave)2∗m
那么,方程就为:
F i , p = min ( F j . p − 1 + ( s i − s j − a v e ) 2 ∗ m ) F_{i,p}=\min(F_{j.p-1}+(s_i-s_j-ave)^2*m) Fi,p=min(Fj.p−1+(si−sj−ave)2∗m)
决策单调性
F j , p + ( s i − s j − a v e ) 2 ∗ m ≥ F k , p + ( s i − s k − a v e ) 2 ∗ m F_{j,p}+(s_i-s_j-ave)^2*m\ge F_{k,p}+(s_i-s_k-ave)^2*m Fj,p+(si−sj−ave)2∗m≥Fk,p+(si−sk−ave)2∗m
对于未来状态 t t t,证明:
F j , p + ( s t − s j − a v e ) 2 ≥ F k , p + ( s t − s k − a v e ) 2 ∗ m F_{j,p}+(s_t-s_j-ave)^2\ge F_{k,p}+(s_t-s_k-ave)^2*m Fj,p+(st−sj−ave)2≥Fk,p+(st−sk−ave)2∗m
s t = s i + v a l ( v a l > 0 ) s_t=s_i+val(val>0) st=si+val(val>0)
只需证明:
− s j ≥ − s k -s_j\ge-s_k −sj≥−sk
s j < s k s_j< s_k sj<sk,证毕。
踢队头
F j , p + ( s i − s j − a v e ) 2 ∗ m ≥ F k , p + ( s i − s k − a v e ) 2 ∗ m F_{j,p}+(s_i-s_j-ave)^2*m\ge F_{k,p}+(s_i-s_k-ave)^2*m Fj,p+(si−sj−ave)2∗m≥Fk,p+(si−sk−ave)2∗m
F j , p + m ∗ ( ( s i − s j ) 2 − 2 ∗ ( s i − s j ) ∗ a v e + a v e 2 ) ≥ F k , p + m ∗ ( ( s i − s k ) 2 − 2 ∗ ( s i − s k ) ∗ a v e + a v e 2 ) F_{j,p}+m*((s_i-s_j)^2-2*(s_i-s_j)*ave+ave^2)\ge F_{k,p}+m*((s_i-s_k)^2-2*(s_i-s_k)*ave+ave^2) Fj,p+m∗((si−sj)2−2∗(si−sj)∗ave+ave2)≥Fk,p+m∗((si−sk)2−2∗(si−sk)∗ave+ave2)
F j , p + m ∗ ( − 2 ∗ s i ∗ s j + s j 2 + 2 ∗ s j ∗ a v e ) ≥ F k , p + m ∗ ( − 2 ∗ s i ∗ s k + s k 2 + 2 ∗ s k ∗ a v e ) ) F_{j,p}+m*(-2*s_i*s_j+{s_j}^2+2*s_j*ave)\ge F_{k,p}+m*(-2*s_i*s_k+{s_k}^2+2*s_k*ave)) Fj,p+m∗(−2∗si∗sj+sj2+2∗sj∗ave)≥Fk,p+m∗(−2∗si∗sk+sk2+2∗sk∗ave))
F k , p − F j , p + m ∗ ( s k 2 − s j 2 + 2 ∗ a v e ∗ ( s k − s j ) ) ≤ 2 ∗ m ∗ s i ∗ ( s k − s j ) F_{k,p}-F_{j,p}+m*({s_k}^2-{s_j}^2+2*ave*(s_k-s_j))\le2*m*s_i*(s_k-s_j) Fk,p−Fj,p+m∗(sk2−sj2+2∗ave∗(sk−sj))≤2∗m∗si∗(sk−sj)
c a l c ( j , k ) = F k , p − F j , p + m ∗ ( s k 2 − s j 2 + 2 ∗ a v e ∗ ( s k − s j ) ) s k − s j ≤ 2 ∗ m ∗ s i calc(j,k)=\frac{F_{k,p}-F_{j,p}+m*({s_k}^2-{s_j}^2+2*ave*(s_k-s_j))}{s_k-s_j}\le2*m*s_i calc(j,k)=sk−sjFk,p−Fj,p+m∗(sk2−sj2+2∗ave∗(sk−sj))≤2∗m∗si
k k k优于 j j j
即
c a l c ( q h e a d , q h e a d + 1 ) ≤ 2 ∗ m ∗ s i calc(q_{head},q_{head+1})\le 2*m*s_i calc(qhead,qhead+1)≤2∗m∗si
q h e a d + 1 q_{head+1} qhead+1优于 q h e a d q_{head} qhead,踢去 h e a d head head
维护一个 c a l c ( q h e a d , q h e a d + 1 ) ≥ 2 ∗ m ∗ s i calc(q_{head},q_{head+1})\ge 2*m*s_i calc(qhead,qhead+1)≥2∗m∗si队列
同时我们可以发现, c a l c ( q h e a d , q h e a d + 1 ) calc(q_{head},q_{head+1}) calc(qhead,qhead+1)随 2 ∗ m ∗ s i 2*m*s_i 2∗m∗si的增大, h e a d head head不断增大,而不断增大。
因此,队列维护的应该是一个下凸壳。
踢队尾
由于维护一个下凸壳,
所以
c a l c ( q t a i l − 1 , q t a i l ) ≤ c a l c ( q t a i l , i − m ) calc(q_{tail-1},q_{tail})\le calc(q_{tail},i-m) calc(qtail−1,qtail)≤calc(qtail,i−m)
反之,
当
c a l c ( q t a i l − 1 , q t a i l ) ≥ c a l c ( q t a i l , i − m ) calc(q_{tail-1},q_{tail})\ge calc(q_{tail},i-m) calc(qtail−1,qtail)≥calc(qtail,i−m)
踢去队尾。
方法2 code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define gc getchar()
#define ll long long
using namespace std;
const int N=3e3+10;
template<class orz>
inline void qr(orz &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
void qw(ll x)
{
if(x<0)x=-x,putchar('-');
if(x/10)qw(x/10);
putchar(x%10+48);
}
double f[N],g[N],ave;int s[N];
inline double calc(int j,int k)
{
return (double)(g[k]-g[j]+s[k]*s[k]-s[j]*s[j]+2*ave*(s[k]-s[j]))/(s[k]-s[j]);
}
int q[N],l,r;
int main()
{
int n,m;qr(n);qr(m);
for(int i=1;i<=n;i++)qr(s[i]),s[i]+=s[i-1];ave=(double)s[n]/m;
for(int i=1;i<=n;i++)f[i]=(s[i]-ave)*(s[i]-ave);
for(int j=2;j<=m;j++)
{
memcpy(g,f,sizeof(g));l=1;r=1;q[1]=j-1;
for(int i=j;i<=n;i++)
{
while(l<r&&calc(q[l],q[l+1])<=2.0*s[i])++l;
while(l<r&&calc(q[r],i)<=calc(q[r-1],q[r]))--r;
q[++r]=i;f[i]=g[q[l]]+(s[i]-s[q[l]]-ave)*(s[i]-s[q[l]]-ave);
}
}
printf("%.0lf\n",f[n]*m);
return 0;
}