可以很好的证明单调决策性质。用 记sum[i]=sigma(C[1],C[2].....C[k]);f[i]=sum[i]+i; c=l-1;
有转移dp[i]=min( dp[j]+(f[i]-f[jk]-c)^2); 假死 有2个决策j<k, 对于i点,k决策更优秀 于是可以得到
dp[k]+(f[i]-f[k]-c)^2<dp[j]+(f[i]-f[j]-c)^2;
对于一个x>i 假设f[x]=f[i]+v;对于决策j,k,若决策k优于决策j ,必然
dp[k]+(f[x]-f[k]-c)^2<dp[j]+(f[x]-f[j]-c)^2;
于是dp[k]+(f[i]+v-f[k]-c)^2<dp[j]+(f[i]-v-f[j]-c)^2;
只要2v(f[i]-f[k]-c)+v^2<2v(f[i]-f[j]-c)
优于v>0 f[k]>f[j] 这是必然成立的 ,所以可以很好的证明单调决策性质,然后可以根据《1D/1D动态规划初步》论文的写法做。
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf = 0x3fffffff;
const int mmax = 500010;
LL C[mmax];
LL dp[mmax];
LL sum[mmax];
int n;
LL L;
struct node
{
int l,r;
int d;
node() {}
node(int l,int r,int d):l(l),r(r),d(d) {}
void print()
{
printf("%d %d %d\n",l,r,d);
}
}Q[mmax];
LL sqr(LL x)
{
return x*x;
}
void up(int i,int j)
{
dp[i]=dp[j]+sqr(sum[i]-sum[j]+i-j-1-L);
}
bool ok(int i,int j,int d)
{
return dp[d]+sqr(sum[i]-sum[d]+i-d-1-L)>=dp[j]+sqr(sum[i]-sum[j]+i-j-1-L);
}
int find(int l,int r,int j,int d)
{
int mid;
r++;
while(l<r)
{
mid=(l+r)>>1;
if(ok(mid,j,d))
r=mid;
else
l=mid+1;
}
return r;
}
void make()
{
int head=0,tail=0;
dp[0]=0;
Q[tail++]=node(0,n,0);
for(int i=1;i<=n;i++)
{
while(Q[head].r<i)
head++;
if(Q[head].l<i)
Q[head].l=i;
up(i,Q[head].d);
int tmp=0;
while(head<tail)
{
if(ok(Q[tail-1].l,i,Q[tail-1].d))
{
tmp=Q[tail-1].l;
tail--;
}
else
{
tmp=find(Q[tail-1].l,Q[tail-1].r,i,Q[tail-1].d);
Q[tail-1].r=tmp-1;
break;
}
}
if(tmp<=n)
Q[tail++]=node(tmp,n,i);
}
}
int main()
{
while(cin>>n>>L)
{
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&C[i]);
sum[i]=sum[i-1]+C[i];
}
make();
printf("%lld\n",dp[n]);
}
return 0;
}