zoukankan      html  css  js  c++  java
  • bzoj3437

    斜率优化

    斜率优化是指对于dp[i]=max/min(dp[j]+a[i]*b[j]+c[j])这样的方程的优化

    -a[i]*b[j]+dp[i]=dp[j]+c[j]

    把b[j]看成x,dp[j]+c[j]看成y

    -a[i]=k dp[i]=b

    这就是一次函数的形式,可以看成用斜率为-a[i]的直线交(x,y),dp就是截距

    对于最大值,我们自然希望截距大,那么就是上凸壳,否则就是下凸壳

    当(x,y)中x单调且-a[i]单调的时候我们可以用队列维护凸壳,因为x单调所以我们可以直接在队尾添加点,又因为-a[i]单调所以每次选的决策肯定是单调的

    如果-a[i]不单调那么我们就得在凸壳上二分

    如果x不单调,那么我们就得用cdq或者splay

    这道题的dp式是dp[i]=dp[j]+(s2[i]-s2[j])*i-(s1[i]-s1[j])+a[i]

    s2是b[i]的前缀和,s1[i]是b[i]*i的前缀和

    那么把只和i有关的去掉

    s2[j]*i+dp[i]=dp[j]+s1[j]

    s2[j]递增 i递增

    由于要最小值,维护下凸壳

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e6 + 5;
    int n;
    ll a[N], b[N], s1[N], s2[N], dp[N];
    int q[N];
    double slope(int i, int j) 
    {
        return (double)(dp[i] - dp[j] + s1[i] - s1[j]) / (double)(s2[i] - s2[j]);
    }
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
        for(int i = 1; i <= n; ++i) scanf("%lld", &b[i]), s1[i] = s1[i - 1] + b[i] * i, s2[i] = s2[i - 1] + b[i];
        int l = 1, r = 1;
        for(int i = 1; i <= n; ++i) 
        {
            while(l < r && slope(q[l], q[l + 1]) <= i) ++l;
            dp[i] = dp[q[l]] + (s2[i] - s2[q[l]]) * i - (s1[i] - s1[q[l]]) + a[i];
            while(l < r && slope(q[r], i) <= slope(q[r], q[r - 1])) --r;
            q[++r] = i;
        }
        printf("%lld
    ", dp[n]);
        return 0;
    }
    View Code
  • 相关阅读:
    pb数据窗口下拉数据窗口列的排序(翻译)
    pb重复行的检查(翻译)
    pb数据窗口如何按当前列的值过滤下拉数据窗口(翻译)
    PB中通过对象名获取对象并获取对象下的子对象
    有关医嘱中的bid,qd等执行频率
    pb数据窗口新增的列编辑后不会分行
    words
    here.less
    Springboot use tomcat JNDI
    genemotion
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8269959.html
Copyright © 2011-2022 走看看