斜率优化

Posted zerolt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了斜率优化相关的知识,希望对你有一定的参考价值。

  1. P2365任务安排((O(n^2))可过题)
    一批任务的准备时间会影响从这批任务开始的所有任务的结束时间
    [f[i]=min_{0le j<i}{f[j]+SumT[i]*(SumC[i]-SumC[j])+s*(SumC[n]-SumC[j])}]
    [BZOJ2726][SDOI202]任务安排(斜率优化+(cdq)分治)cdq分治我们不熟

  2. [APIO2010]特别行动队
    [f_i=max_{0le j<i}{f_j+a(s_i-s_j)^2+b(s_i-s_j)+c}]
    变形一下
    [f_i=f_j+as_i^2-2as_is_j+as_j^2+bs_i-bs_j+c]
    [f_j-as_j^2+bs_j=-2as_is_j+f_i+as_i^2+bs_i]
    [X_j=s_j] [Y_j=f_j-as_j^2+bs_j]
    [K_i=-2as_i] [B_i=f_i+as_i^2+bs_i]
    (ecause a < 0)( herefore K_i < 0), 且(K)递增,要使(B)最大,维护上凸包
double eps=1e-7;
int dcmp(double x){if(fabs(x) <= eps) return 0; return x > 0 ? 1 : -1;}
double Y(int x){return f[x]+a*s[x]*s[x]-b*s[x];}
double X(int x){return s[x];}
double slope(int i, int j){
        double x1=X(i), y1=Y(i), x2=X(j), y2=Y(j);
        return (y1-y2)/(x1-x2);
}
int q[Maxn], l, r;
void solve(){
        n=read(); a=read(), b=read(), c=read(); for(int i=1; i <= n; i++) s[i]=s[i-1]+read();
        l=r=1, q[1]=0;
        for(int i=1; i <= n; i++){
            while(l < r && dcmp(slope(q[l], q[l+1]) - 1.0*a*2*s[i]) > 0) l++;
            f[i]=f[q[l]]+a*(s[i]-s[q[l]])*(s[i]-s[q[l]])+b*(s[i]-s[q[l]])+c;
            while(l < r && dcmp(slope(q[r-1], q[r])-slope(q[r], i) <= 0)) r--;
            q[++r]=i;
        }
        printf("%.0lf", f[n]);
}
  1. [HNOI2008]玩具装箱TOY
    (S_i=sum_{j=1}^iC_j),(P_i=S_i+i)
    [f_i=min_{0le j<i}{f_j+(P_i-P_j-1-L)^2}]
    [f_i=f_j+P_i^2-2P_iP_j+P_j^2-2(L+1)(P_i-P_j)+(L+1)^2]
    [f_j+P_j^2=2(P_i-L-1)P_j+f_i-P_i^2+2(L+1)P_i+(L+1)^2]
    [X_j=P_j] [Y_j=f_j+P_j^2]
    [K_i=2(P_i-L-1)] [B_i=f_i-P_i^2+2(L+1)P_i+(L+1)^2]
    (ecause P_i > 0, herefore K_i)递增,要使(B_i)最小,维护下凸包
#define a(i) (sum[i]+i)
#define b(i) (a(i)+L+1)
#define Y(i) (dp[i]+b(i)*b(i))
#define X(i) b(i)
#define slope(i, j) ((Y(i)-Y(j))/(X(i)-X(j)))
int q[N], head, tail;
void solve(){
        n=read(), L=read(); head=tail=1;
        for(int i=1; i <= n; i++){
            sum[i]=sum[i-1]+read();
            while(head < tail && slope(q[head], q[head+1]) < 2*a(i)) head++;
            dp[i]=dp[q[head]]+(a(i)-b(q[head]))*(a(i)-b(q[head]));
            while(head < tail && slope(i, q[tail-1]) < slope(q[tail-1], q[tail])) tail--;
            q[++tail]=i;
        }
        printf("%lld
", dp[n]);
}
  1. [SDOI2016]征途
    (S_i)为每天的路程长度,(sum)为总路程,先推(vm^2)
    [Delta S=frac{sum}{m}]
    [vm^2=msum_{i=1}^m(S_i-Delta S)^2]
    [=msum_{i=1}^mS_i^2-2Delta SS_i+Delta S^2]
    [=msum_{i=1}^mS_i^2-sum^2]
    所以令(f_{(i, j)})为前(i)段路分为(j)天走的最小(sum_{i=1}^jS_i)
    [f_{(i, j)}=min_{j-1le k<i}{f_{(k, j-1)}+(Sum_{i}-Sum_k)^2}]
    不管(j),
    [f_i=f_k+Sum_i^2-2Sum_iSum_k+Sum_k^2]
    [f_k+Sum_k^2=f_i-Sum_i^2+2Sum_iSum_k]
    [X_k=Sum_k] [Y_k=f_k+Sum_k^2]
    [K_i=2Sum_i]
    [B_i=f_i-Sum_i^2]
    (B_i)最小,(ecause K_i)递增,( herefore)维护下凸包
int q[Maxn], l, r;
ll *f=f1, *g=g1;
double X(int i) {return S[i];}
double Y(int i) {return g[i]+S[i]*S[i];}
double slope(int i, int j){
    double x1=X(i), y1=Y(i), x2=X(j), y2=Y(j);
    return (y1-y2)/(x1-x2);
}
void solve(){
        n=read(), m=read(); for(int i=1; i <= n; i++) S[i]=S[i-1]+read(), f[i]=S[i]*S[i];
        for(int i=1; i < m; i++){
            l=r=1; q[1]=i; swap(f, g);
            for(int j=i+1; j <= n; j++){
                while(l < r && slope(q[l], q[l+1]) <= 2.0*S[j]) l++;
                f[j]=g[q[l]]+(S[j]-S[q[l]])*(S[j]-S[q[l]]);
                while(l < r && slope(q[r], q[r-1]) >= slope(q[r], j)) r--;
                q[++r]=j;
            }
        }
        printf("%lld", f[n]*m-S[n]*S[n]);
}
  1. [CF311B]Cats Transport































以上是关于斜率优化的主要内容,如果未能解决你的问题,请参考以下文章

UVALive 4726 Average ——(斜率优化DP)

3156: 防御准备(斜率优化)

hdu 3480 Division(斜率优化)

hdu 3507 Print Article(斜率优化)

bzoj 4709 [ Jsoi 2011 ] 柠檬 ——斜率优化DP

hdu 1300 Pearls(线性dp/斜率优化)