1 条题解
-
0
这是12分代码
/* f[i]表示 1 跳到 i 的最小花费 f[i]=min( f[j]+ (h[i]-h[j])^2)+C ) (j<i) f[1]=0; for(int i = 2; i <= n; ++ i) { f[i] = 1e16; for(int j = 1; j < i; ++ j) f[i] = min(f[i], f[j] + (h[i] - h[j]) * (h[i] - h[j]) + C); } n=2e5,时间复杂度O(n^2)会超时 */这是100分代码
/* f[i]=min( f[j]+ (h[i]-h[j])^2)+C ) (j<i) f[i]=f[j]+h[i]^2+h[j]^2-2*h[i]*h[j]+C 目标是:kx + b = y 2*h[i]*h[j] + f[i]-h[i]^2-C = f[j]+h[j]^2 k=2*h[i](固定),x=h[j](可变) , b=f[i]+h[i]^2-C(希望最小) , y=f[j]+h[j]^2(由x固定) 1、y[j]和x[j]是已计算好的,而且可选, 2、k是固定的, 3、选择不一样的j能够使得b最小:即固定斜率,选过一个点,使得和y轴的截距最小。 b变小,也意味着f[i]变小。 */ #include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=2e5+10; LL h[N],f[N],C; int q[N]; double X(int j){return 1.0*h[j];} double Y(int j){return 1.0*(f[j]+h[j]*h[j]);} double slop(int j1,int j2){return X(j2)==X(j1)? 1e18*( Y(j2)-Y(j1) ) :( Y(j2)-Y(j1) ) / ( X(j2)-X(j1) );} int main() { int n;scanf("%d%lld",&n,&C); for(int i=1;i<=n;i++) scanf("%lld",&h[i]); int l=1,r=1;q[1]=1;f[1]=0; for(int i=2;i<=n;i++) { while( (l<r)&&( slop(q[l],q[l+1])<=2*h[i] ) )l++; f[i]=f[q[l]]+(h[i]-h[q[l]])*(h[i]-h[q[l]])+C; while( (l<r)&&( slop(q[r-1],q[r])>=slop(q[r],i) ) )r--; q[++r]=i; } printf("%lld\n",f[n]); return 0; }
- 1
信息
- ID
- 2209
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 8
- 标签
- 递交数
- 89
- 已通过
- 16
- 上传者