zoukankan      html  css  js  c++  java
  • 斜率dp

    HUD-3507
    Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate this degree.
    One day Zero want to print an article which has N words, and each word i has a cost Ci to be printed. Also, Zero know that print k words in one line will cost

    [(sum_{i=1}^kC_i)^2+M ]

    M is a const number.
    Now Zero want to know the minimum cost in order to arrange the article perfectly.

    Input
    There are many test cases. For each test case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines. Input are terminated by EOF.

    Output
    A single number, meaning the mininum cost to print the article.

    Sample Input

    5 5
    5
    9
    5
    7
    5
    

    Sample Output

    230
    

    很容易推出:(dp[i]=min(dp[j]+(s[i]-s[j])^2+M)) 其中(j<i)
    这样的不加优化的裸dp是(O(n^2))的,5e5的数据肯定爆了
    假设(k<j<i)
    如果对于dp[i], j 比 k 优,有
    (dp[j]+(s[i]-s[j])^2+M)<dp[k]+(s[i]-s[k])^2+M))

    (dp[j]+s[j]^2-(dp[k]+s[j]^2)<2s[i](s[j]-s[k]))

    设$$g(k,j)=frac{dp[j]+s[j]2-(dp[k]+s[j]2)}{2(s[j]-s[k])}<s[i]$$
    也就是$$frac{y2-y1}{x2-x1}<k$$
    如果(g(k,j)<s[i]),说明j比k优,且s[i]是递增的,j永远比k优
    如果(g(a,b)>g(b,c)) b永远不是较优的:

    1. (g(b,c)<=s[i]),c比b优或一样
    2. (g(b,c)>s[i]),b比c优但是a比b优,所以a优

    所以,可以用队列维护一个下凸包,为何不是栈呢,这点想了好久,如果j比k优,j永远比k优,所以没用的就扔了。

    #include<bits/stdc++.h>
    #include<iostream>
    using namespace std;
    template<class T> inline bool read(T &x){
        x=0;register char c=getchar();register bool f=0;
        while(!isdigit(c)){if(c==EOF)return false;f^=c=='-',c=getchar();}
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        if(f)x=-x;
        return true;
    }
    typedef long long ll;
    const ll MAXN=5e5+8,inf=0x3f3f3f3f,mod=1e9+7;
    int n,m;
    int s[MAXN],dp[MAXN],cnt;
    int que[MAXN],l,r;//队列  [l,r)
    inline int dy(int a,int b){return dp[a]+s[a]*s[a]-dp[b]-s[b]*s[b];}
    inline int dx(int a,int b){return 2*(s[a]-s[b]);}//a>b,如果不是这样,返回负数,不等式要变号
    inline void up(int i,int j){dp[i]=dp[j]+(s[i]-s[j])*(s[i]-s[j])+m;}//用j更新i
    int main() {
        while(read(n)&&read(m)){
            for(int i=1;i<=n;++i){
                read(s[i]);
                s[i]+=s[i-1];
            }
            l=r=0;
            que[r++]=0;
            for(int i=1;i<=n;++i){
                while(l<r-1&&dy(que[l+1],que[l])<=s[i]*dx(que[l+1],que[l]))l++;//直接l++,而不是零时变量
                up(i,que[l]);
                while(l<r-1&&dy(que[r-1],que[r-2])*dx(i,que[r-1])>=dy(i,que[r-1])*dx(que[r-1],que[r-2]))r--;
                que[r++]=i;
            }printf("%d
    ",dp[n]);
        }
        return 0;
    }
    

    每个i入队一次,出队最多一次,所以是O(n)

  • 相关阅读:
    Dark 运算符
    Dark 数据类型
    分支管理
    Git 远程仓库
    DELPHI实现百度开放平台
    win2008使用FireDac连接ORACLE数据库问题
    20160115学习日志
    20160113第一个ANDRIOD开发日志
    struts2漏洞与修复
    DELPHI XE5 与SQLITE
  • 原文地址:https://www.cnblogs.com/foursmonth/p/14155949.html
Copyright © 2011-2022 走看看