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)

  • 相关阅读:
    SpringBoot-13-简单整合Dubbo
    SpringBoot-12-整合Redis
    SpringBoot-11-任务
    SpringBoot-10-Swagger
    SpringBoot-09-Apche Shiro
    SpringBoot-08-Spring Security
    五十七-代码审计-JAVA项目框架类漏洞分析报告
    五十六:代码审计-JAVA项目Filter过滤器及XSS挖掘
    五十五:代码审计-JAVA项目注入上传搜索或插件挖掘
    五十四:代码审计-TP5框架审计写法分析及代码追踪
  • 原文地址:https://www.cnblogs.com/foursmonth/p/14155949.html
Copyright © 2011-2022 走看看