zoukankan      html  css  js  c++  java
  • hdu3507 Print Article

    Print Article

     HDU - 3507 

    【题目标题】:

    打印文章

    给出N个单词,每个单词有个非负权值Ci,现在要将它们分成连续的若干段,每段的代价为此段单词的权值和的平方,还要加一个常数M,即。现在想求出一种最优方案,使得总费用之和最小。

    【输入格式】

    包含多组测试数据,对于每组测试数据。 第一行包含两个整数N和M(0<=N<=500000,0<=M<=1000)。 第2-N+1行为N个整数。

    【输出格式】

    输出仅一个整数,表示最小的价值。

    【样例输入】

    5 5
    5
    9
    5
    7
    5
    3 0
    1
    2
    3

    【样例输出】

    230
    14

    sol:题目中特意把n≤500000标红意思是说n2绝对凉凉
    对于我这种菜鸡,只会先把暴力打出来再看
    k
    对于前缀和Qzhi=∑ Ci
      i=1

    dp[i]=min(dp[i],dp[j]+(Qzh[i]-Qzh[j])2+m)
    似乎我只会这样就完了(题解大法好!!!)

    斜率优化dp
    dp[i]=dp[j]+Qzh[i]2-2*Qzh[i]*Qzh[j]+Qzh[j]2+m
    对于j<k<i,如果k比j要优
    则满足 dp[k]+Qzh[i]2-2*Qzh[i]*Qzh[k]+Qzh[k]2+m ≤ dp[j]+Qzh[i]2-2*Qzh[i]*Qzh[j]+Qzh[j]2+m
    消去一样的可得 dp[k]-2*Qzh[i]*Qzh[k]+Qzh[k]2
    ≤ dp[j]-2*Qzh[i]*Qzh[j]+Qzh[j]2
    移项可得 dp[k]+Qzh[k]2-dp[j]-Qzh[j]2
    ≤ 2*Qzh[i]*(Qzh[k]-Qzh[j])
    所以可知 当(j<k<i) dp[k]+Qzh[k]2-dp[j]-Qzh[j]2 ≤ 2*Qzh[i]*(Qzh[k]-Qzh[j])时 k 比 j 优
    设 G[j][k]表示 G[j,k]=((dp[k]+Qzh[k]2)-(dp[j]+Qzh[j]2))/(2*Qzh[i]*(Qzh[k]-Qzh[j]))
    当G[j][k]<=1 k优于j,否则j优于k (其实G[j][k]就是斜率)
    当(j<k<i) 当G[j][k]>=G[k][i],k就没用了

    /*
        //dp[i]表示输出到第i位的最小费用
        //因此很容易推出dp[i]=min(dp[i],dp[j]+(sum[i]-sum[j])^2+m)
        //但是复杂度为O(n^2),一定会超时,
                    
        //假设j<k,假设k优于j
        //dp[k]+(sum[i]-sum[k])^2+m<dp[j]+(sum[i]-sum[j])^2+m
        //G[j,k]=((dp[k]+sum[k]^2)-(dp[j]+sum[j]^2))/(2*sum[i]*(sum[k]-sum[j]))<=1时
        //假设成立,也就是k优于j,否则j优于k
        //当k1<k<k2时,G[k1,k]>=G[k,k2]时,k没有用处
    */
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0');    return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=500005;
    int n,m;
    int Queue[N];
    ll Qzh[N],dp[N];
    #define Sqr(x) ((x)*(x))
    inline bool Pand(int j,int k,int i) //j<k<i
    {
        ll P1=dp[k]+Sqr(Qzh[k])-dp[j]-Sqr(Qzh[j]);
        ll P2=2*Qzh[i]*(Qzh[k]-Qzh[j]);
        return (P1<=P2)?(1):(0);
    }
    inline bool Pand_Rev(int j,int k,int i) //j<k<i
    {
        ll P1=(dp[k]+Sqr(Qzh[k])-dp[j]-Sqr(Qzh[j]))*(Qzh[i]-Qzh[k]);
        ll P2=(dp[i]+Sqr(Qzh[i])-dp[k]-Sqr(Qzh[k]))*(Qzh[k]-Qzh[j]);
        return (P1>=P2)?(1):(0);
    }
    int main()
    {
        int i,j;
        while(~scanf("%d%d",&n,&m))
        {
            for(i=1;i<=n;i++)
            {
                Qzh[i]=Qzh[i-1]+read();
            }
            int Head=0,Tail=0; Queue[0]=0;
            for(i=1;i<=n;i++)
            {
                while(Head<Tail&&Pand(Queue[Head],Queue[Head+1],i)) Head++;
                dp[i]=dp[Queue[Head]]+Sqr(Qzh[i]-Qzh[Queue[Head]])+m;
                while(Head<Tail&&Pand_Rev(Queue[Tail-1],Queue[Tail],i)) Tail--;
                Queue[++Tail]=i;
            }
            Wl(dp[n]);
        }
        return 0;
    }
    /*
    input
    5 5
    5
    9
    5
    7
    5
    3 0
    1
    2
    3
    output
    230
    14
    */
    View Cod
  • 相关阅读:
    SQL Server, Timeout expired.all pooled connections were in use and max pool size was reached
    javascript 事件调用顺序
    Best Practices for Speeding Up Your Web Site
    C语言程序设计 使用VC6绿色版
    破解SQL Prompt 3.9的几步操作
    Master page Path (MasterPage 路径)
    几个小型数据库的比较
    CSS+DIV 完美实现垂直居中的方法
    由Response.Redirect引发的"Thread was being aborted. "异常的处理方法
    Adsutil.vbs 在脚本攻击中的妙用
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10393118.html
Copyright © 2011-2022 走看看