斜率优化。。。
推式子QAQ
令:$sum_i$为$C_{1~i}$的前缀和 ,$f_i=sum_i+i$
显然:$dp_i=min{kin{[1,i-1]}dp_k+[f_i-f_k-(L-1)]}$
最后得到:
若$k$比$j$对于$i$更优,则:
$[dp[k]+(f_k+L+1)^2-dp[j]+(f_j+L+1)^2]/[2 imes(f_k-f_j)]leqslant f_i$
然后斜率优化……
1 #include<cstdio> 2 #include<cstdlib> 3 #include<string> 4 #include<cstring> 5 #include<cmath> 6 #include<iostream> 7 #define re(i,l,r) for(int i=(l);i<=(r);i++) 8 using namespace std; 9 typedef long long LL; 10 template <typename Q> 11 void inin(Q &ret) 12 { 13 ret=0;int f=0;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} 15 while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); 16 ret=f?-ret:ret; 17 } 18 int n,L,c[50050],que[50050]; 19 LL dp[50050],f[50050]; 20 double ff(const double &a){return a*a;} 21 double k(int j,int k) 22 { 23 return (dp[k]+ff(f[k]+L+1)-dp[j]-ff(f[j]+L+1))/(2.*(f[k]-f[j])); 24 } 25 int main() 26 { 27 inin(n),inin(L); 28 re(i,1,n)inin(c[i]); 29 re(i,1,n)f[i]=f[i-1]+c[i]; 30 re(i,1,n)f[i]+=i; 31 int l=1,r=0;que[++r]=0; 32 re(i,1,n) 33 { 34 while(l<r&&k(que[l],que[l+1])<=f[i])l++; 35 int t=que[l]; 36 dp[i]=dp[t]+(f[i]-f[t]-L-1)*(f[i]-f[t]-L-1); 37 while(l<r&&k(que[r],i)<k(que[r-1],que[r]))r--; 38 que[++r]=i; 39 } 40 printf("%lld",dp[n]); 41 return 0; 42 }