DP~斜率优化

简介:

  • dp d p 的转移方程中, 对不必要的状态量进行抛弃,对不优的状态量进行搁置,使得在常数时间内找到最优解成为可能。
  • 斜率优化依靠的是数形结合的思想,通过将每个阶段和状态的答案反映在座标系上寻找解答的单调性,来在一个单调的答案(下标)队列中O(1)得到最优解。
  • 斜率优化 dp d p 其实是单调队列的推广,单调队列、旋转卡壳、斜率优化都利用了单调性降低时间复杂度。

分析:

  • 形如 dp d p 转移方程: dp[i]=min/max d p [ i ] = m i n / m a x { dp[j]+g[j]x[i]+M d p [ j ] + g [ j ] ∗ x [ i ] + M }
  • 对于这一类转移我们可以化成 kx+y k ∗ x + y 最值的问题我们可以通过凸包的制造是最优解满足单调性质(当k有序是此时我们用到的节点以后一定不会用到)
  • 对于求 min m i n dp d p ,一般最后的不等式化简得到 dydx<k d y d x < k ,那么应该用下凸包
  • 同理,对于求 max m a x dp d p ,一般最后的不等式化简得到 dydx>k d y d x > k ,那么应该用上凸包

模板(code):

LL getY(int p1,int p2){//dy
    return dp[p2]-dp[p1];
}

LL getX(int p1,int p2){//dx
    return g[p2]-g[p1];
}

LL getDP(int p1,int p2){//转移
    return dp[p2]+g[p2]*x[p1]+M;
}

int main(){
    read();

    L=R=0;
    Q[R++]=0;

    REP(i,1,n){
        while(L+1<R && getY(Q[L],Q[L+1])<=-x[i]*getX(Q[L],Q[L+1]))L++;
        dp[i]=getDP(i,Q[L]);
        while(L+1<R && getY(Q[R-1],i)*getX(Q[R-2],Q[R-1])<=getY(Q[R-2],Q[R-1])*getX(Q[R-1],i))R--;
// while(L+1<R && slope(Q[R-2],Q[R-1],i)))R--; 
        //维护时,可以用叉积或判斜率,取决于是否炸 long long
        Q[R++]=i;   
    }
    // 建议还是画一画凸包感受一下...
    put();
    return 0;
}

总结:

  • 首先要满足斜率优化的条件吧…那么可以将 O(n)>O(logn) O ( n ) − > O ( l o g n )
  • 在凸包的问题中,会遇到一些不满足单调的情况,那么就要三分或二分去找最优解了。
点赞