zoukankan      html  css  js  c++  java
  • [BZOJ 1911] 特别行动队

    Link:

     传送门

    Algorithm:

    DP方程:$dp[i]=max(dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c)$

    方程是显然的,但复杂度为$O(N^2)$,需要优化到$O(N)$,这时就需要斜率优化了

    推荐博客:https://www.cnblogs.com/MashiroSky/p/6009685.html

    这篇博客清晰地从“数”到“形”展现了斜率优化

    其中必要的前提:dp数组是要具有决策单调性的

    (即如果在$dp[i]$下决策$j$好于$k$,那么在大于$i$时$j$永远要好于$k$)

    同时与i相关的数组具有单调性(不具有决定性,可以通过凸包二分来解决非单调性问题

    此题符合这几个前提,

    如果$j>k$且$j$比$k$更优 :(由决策单调性推出)

    $dp[j]-dp[k]+a*sum[j]^2-a*sum[k]^2+b*(sum[k]-sum[j])>2*a*(sum[j]-sum[k])*sum[i]$

    $slope(j,k)=frac{dp[j]-dp[k]+a*sum[j]^2-a*sum[k]^2+b*(sum[k]-sum[j])}{2*a*(sum[j]-sum[k])}>sum[i]$

    用单调队列维护$slope$

    1、使$slope(cur,cur+1)$保持递增,因为$sum[i]$递增

    2、由于$slope(j,k)>sum[i]$时决策$j$比$k$更优,因此决策$head$>$head+1$>……$tail$

    每次将$slope(head,head+1) < sum[i]$的$head$踢出队列,之后的$queue[head]$即为最优决策

    记住,SLOPE只是用于判断在$sum[i]$时$j$比$k$优的结论是否成立,我们用优先队列来优化维护其的复杂度

    $slope(j,k)$和$slope(j'' ,  k'')$间的大小关系与决策的优越性不具有直接联系

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAXN=1e6+10;
    
    ll pre[MAXN],dp[MAXN],que[MAXN],l,r,a,b,c,n;
    
    inline ll read()
    {
        char ch;ll num,f=0;
        while(!isdigit(ch=getchar())) f|=(ch=='-');
        num=ch-'0';
        while(isdigit(ch=getchar())) num=num*10+ch-'0';
        return f?-num:num;
    }
    
    ll sqr(ll x){return x*x;}
    
    inline double slope(int x,int y)
    {
        return (double)(dp[x]-dp[y]+a*sqr(pre[x])-a*sqr(pre[y])+b*(pre[y]-pre[x]))/(double)(2*a*(pre[x]-pre[y]));
    }
    
    int main()
    {
        n=read();a=read();b=read();c=read();
        for(int i=1;i<=n;i++) pre[i]=read(),pre[i]+=pre[i-1];
        
        for(int i=1;i<=n;i++)
        {
            while(l<r && slope(que[l],que[l+1])<=pre[i]) l++;
            dp[i]=dp[que[l]]+a*sqr(pre[i]-pre[que[l]])+b*(pre[i]-pre[que[l]])+c;
            while(l<r && slope(que[r],i)<=slope(que[r-1],que[r])) r--;
            que[++r]=i;
        }
        cout << dp[n];
        
        return 0;
    }

    Review:

    1、如果转移方程显而易见,但要优化复杂度

    只要其具有决策单调性,且可由其推出的式子发现与i相关的量可看成斜率  /  转移方程中的dp[i]可看作截距

    均可使用斜率优化

    2、当与i相关的数组不具有单调性时,要利用二分/三分法找到对应斜率(Updating)

  • 相关阅读:
    蛙蛙请教:把一段c算法代码转换成c#代码。
    和病毒折腾了两天
    WawaKM预览版发布,欢迎大家测试反馈哦
    (转)深度分析如何在Hadoop中控制Map的数量
    [转载]JAVA操作符
    (转)Hive Index
    Hadoop++:Hadoop的局部性能改良
    深入了解Hive Index具体实现
    Linux echo命令
    (转)带索引的mapReduce
  • 原文地址:https://www.cnblogs.com/newera/p/9058356.html
Copyright © 2011-2022 走看看