1 条题解

  • 0
    @ 2025-10-8 17:00:24

    这是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
    上传者