斜率优化求助
查看原帖
斜率优化求助
35754
whiteqwq楼主2020/8/9 22:41

过不了样例(输出14)

附推导过程:

转移方程:

fi=minj=1i1{fj+((i(j+1)+sumisumj)l)2}f_i=\min_{j=1}^{i-1}\{f_j+((i-(j+1)+sum_{i}-sum_j)-l)^2\}

j,kj,kii的两个决策点,k<j<ik<j<i,且jjkk更优那么: fj+(ij1+sumisumjl)2<fk+(ik1+sumisumkl2)f_j+(i-j-1+sum_i-sum_j-l)^2<f_k+(i-k-1+sum_i-sum_k-l^2)

定义g(i)=i+sumi,h(i)=i+sumil1g(i)=i+sum_i,h(i)=i+sum_i-l-1

fj+(h(i)g(j))2<fk+(h(i)g(k))2f_j+(h(i)-g(j))^2<f_k+(h(i)-g(k))^2

fjfk<(h(i)2+g(k)22h(i)g(k))(h(i)2+g(j)22h(i)g(j))f_j-f_k<(h(i)^2+g(k)^2-2\cdot h(i)\cdot g(k))-(h(i)^2+g(j)^2-2\cdot h(i)\cdot g(j))

fjfk<g(k)2g(j)22h(i)(g(k)g(j))f_j-f_k<g(k)^2-g(j)^2-2\cdot h(i)\cdot(g(k)-g(j))

fjfk<(g(k)g(j))(g(k)+g(j))2h(i)(g(k)g(j))f_j-f_k<(g(k)-g(j))(g(k)+g(j))-2\cdot h(i)\cdot(g(k)-g(j))

因为g(k)=k+sumk<j+sumk<j+sumj=g(j)g(k)=k+sum_k<j+sum_k<j+sum_j=g(j),所以除以g(k)g(j)g(k)-g(j)需要反号

fjfkg(k)g(j)>g(k)+g(j)2h(i)\frac{f_j-f_k}{g(k)-g(j)}>g(k)+g(j)-2\cdot h(i)

(g(k)+g(j))(g(k)g(j))+fjfkg(k)g(j)>2h(i)\frac{-(g(k)+g(j))(g(k)-g(j))+f_j-f_k}{g(k)-g(j)}>-2\cdot h(i)

fj+g(j)2fkg(k)2g(j)g(k)<2h(i)\frac{f_j+g(j)^2-f_k-g(k)^2}{g(j)-g(k)}<2\cdot h(i)

#include<stdio.h>
#define inf 1000000000
const int maxn=50005;
int i,j,k,m,n,L,l,r;
int c[maxn],sum[maxn],q[maxn],f[maxn];
inline int g(int p){
	return p+sum[p];
}
inline int h(int p){
	return p+sum[p]-L-1;
}
inline int x(int p){
	return f[p]+g(p)*g(p);
}
inline int y(int p){
	return g(p);
}
inline double slope(int a,int b){
	if(x(a)==x(b))
		return y(a)<=y(b)? 1.0*inf:-1.0*inf;
	return 1.0*(y(a)-y(b))/(x(a)-x(b));
}
int main(){
	scanf("%d%d",&n,&L);
	for(i=1;i<=n;i++)
		scanf("%d",&c[i]);
	for(i=1;i<=n;i++)
		sum[i]=sum[i-1]+c[i];
	l=1,r=0,q[++r]=0;
	for(i=1;i<=n;i++){
		while(l<r&&slope(q[l+1],q[l])<=2.0*h(i))
			l++;
		f[i]=f[q[l]]+(h(i)-g(q[l]))*(h(i)-g(q[l]));
		while(l<r&&slope(q[r],q[r-1])>=slope(i,q[r]))
			r--;
		q[++r]=i;
	}
	printf("%d\n",f[n]);
	return 0;
}
2020/8/9 22:41
加载中...