zoukankan      html  css  js  c++  java
  • HDU3507_Print Article

     这个题目又是一个典型的dp斜率优化的题目。题意是给你n个数,你需要做的是把这个n个数分为连续的若干段,每段的权值为这段数字的和的平方加上M。求最小的总权值。

    我们可以根据题意写出朴素版的dp状态转移方程。然后就可以推导出使用优先队列来维护最优值。总共包括对首和队尾的两个操作。

    很简单,很朴素的题目,直接上代码吧。。。。就是范围定义小了,然后Wa了n^n^n^n^……发。 深坑啊。。。

     

     

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define maxn 500500
    #define ll long long
    using namespace std;
    
    ll f[maxn],a[maxn],sum[maxn];
    ll n,m,xx,yy,xx1,yy1;
    ll q[maxn],head,tail;
    
    ll dy(ll j1,ll j2) { return f[j2]+sum[j2]*sum[j2]-f[j1]-sum[j1]*sum[j1]; }
    
    ll dx(ll j1,ll j2) { return 2*(sum[j2]-sum[j1]); }
    
    int main()
    {
        while (scanf("%I64d%I64d",&n,&m)!=EOF)
        {
            for (ll i=1; i<=n; i++) scanf("%I64d",&a[i]),sum[i]=sum[i-1]+a[i];
            head=tail=1,q[1]=0;
            for (ll i=1; i<=n; i++)
            {
                while (tail-head>0)
                {
                    xx=dx(q[head],q[head+1]);
                    yy=dy(q[head],q[head+1]);
                    if (sum[i]*xx>=yy) head++;
                        else break;
                }
                f[i]=f[q[head]]+(sum[i]-sum[q[head]])*(sum[i]-sum[q[head]])+m;
                while (tail-head>0)
                {
                    yy=dy(q[tail-1],q[tail]);
                    xx=dx(q[tail-1],q[tail]);
                    yy1=dy(q[tail],i);
                    xx1=dx(q[tail],i);
                    if (yy*xx1>=yy1*xx) tail--;
                        else break;
                }
                q[++tail]=i;
            }
            printf("%I64d
    ",f[n]);
        }
        return 0;
    }

     

    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    java ssh免密登录
    [8.0][MGR][bug]多主模式,外键冲突错误
    内核月报bookmark
    netcat 传输T级别大文件
    innodb部分内部操作
    qps.sh
    ABAP-ALV判断骚操作
    HCM基本知识
    SAP-VOFM的使用
    ABAP-处理去掉特殊字符
  • 原文地址:https://www.cnblogs.com/lochan/p/3425812.html
Copyright © 2011-2022 走看看