很容易地,我们首先得到:
s[x]=min{s[k]+(p[x]−p[k]+x−k−L−1)2}
其中,p[n]=∑ni=1C[i]
这样直接计算是会TLE的: O(n2)
下面我们考虑优化:
我们记f[x]=p[x]+x,c=L+1,那么方程简化为:
s[x]=min{s[k]+(f[x]−f[k]−c)2}
先看下决策单调性
设k>j且有
s[k]+(f[x]−f(k)−c)2<s[j]+(f[x]−f[j]−c)2(1)
对于以后的决策,设 y>x 并记f[y]=f[x]+Δ 显然Δ>0
若我们的方程有决策单调性那么我们就有:
s[k]+(f[y]−f[k]−c)2<s[j]+(f[y]−f[j]−c)2
也即
s[k]+(f[x]+Δ−f[k]−c)2<s[j]+(f[x]+Δ−f[j]+c)2
s[k]+(f[x]−f[k]−c)2+2(f[x]−f[k]−c)Δ<s[j]+(f[x]−f[j]−c)2+2(f[x]−f[j]−c)Δ
我们考虑到两个不等式: 2(f[x]−f[k]−c)Δ<2(f[x]−f[j]−c)Δ 也即 f[k]>f[j]
s[k]+(f[x]−f[x]−c)2<s[j]+(f[x]−f[j]−c)2
两式相加即得我们迫切想看到的决策单调性
即决策点只向右移动.
我们只有决策单调性是不够的,我们还可以从(1)中获取更多信息
我们将(1)打开,并将所有有关j,k的项移到一边就有
s[k]−2cf[k]+f[k]2−(s[j]−2cf[j]+f[j]2)f[k]−f[j]<2f[x]
嘿!这是什么,斜率?对的.
我们可以以(f[x],s[x]−2cf[x]+f[x]2)为点x的坐标画出散点图,再从中找出它的右下凸包,我们仅考虑也仅维护这个凸包,当我们要算s[y]时,我们就找凸包上的一个点t,使得它与前面一个点连线的斜率小于2f[y]与后面一个点的斜率大于2f[y] (也就是切线)那么这个点就是最优决策点.我们可以二分做到(凸包上斜率递增).
算完s[y]后,我们要将它插入凸包中(它一定在凸包中)这又可以在O(logn)的时间内完成.
这样,我们对每个点用O(logn)时间搜索最优决策点,用O(logn)时间插入新点
总用时O(nlogn)对n<50001绰绰有余.