zoukankan      html  css  js  c++  java
  • HDU

     1 #include <iostream>
     2 #include <queue>
     3 #include <stack>
     4 #include <cstdio>
     5 #include <vector>
     6 #include <map>
     7 #include <set>
     8 #include <bitset>
     9 #include <algorithm>
    10 #include <cmath>
    11 #include <cstring>
    12 #include <cstdlib>
    13 #include <string>
    14 #include <sstream>
    15 #include <time.h>
    16 #define x first
    17 #define y second
    18 #define pb push_back
    19 #define mp make_pair
    20 #define lson l,m,rt*2
    21 #define rson m+1,r,rt*2+1
    22 #define mt(A,B) memset(A,B,sizeof(A))
    23 #define lowbit(x) (x&(-x))
    24 using namespace std;
    25 typedef long long LL;
    26 //const double PI = acos(-1);
    27 const int N=5e5+10;
    28 const LL mod=1e9+7;
    29 const int inf = 0x3f3f3f3f;
    30 const LL INF=0x3f3f3f3f3f3f3f3fLL;
    31 const double esp=1e-10;
    32 int n,q[N];
    33 LL m,sum[N],dp[N];
    34 //dp的斜率优化就是把那些没用的点舍弃,降低尝试次数从而提高效率。
    35 //如果up(j,k)/down(j,k)<=sum[i],则说明位置j比位置k更优,则位置k可以直接舍弃。
    36 //维护一个下凸折线,用单调队列维护,类似凸包的维护。
    37 LL up(int j,int k)//斜率优化时的分子
    38 {
    39     return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];
    40 }
    41 LL down(int j,int k)//斜率优化时的分母
    42 {
    43     return 2*sum[j]-2*sum[k];
    44 }
    45 int main()
    46 {
    47 #ifdef Local
    48     freopen("data.txt","r",stdin);
    49 #endif
    50     ios::sync_with_stdio(false);
    51     cin.tie(0);
    52     while(cin>>n>>m)
    53     {
    54         int head=0,tail=0;
    55         sum[0]=0;dp[0]=0;
    56         for(int i=1;i<=n;i++)
    57         {
    58             cin>>sum[i];
    59             sum[i]+=sum[i-1];
    60         }
    61         q[tail++]=0;
    62         for(int i=1;i<=n;i++)
    63         {
    64             //从head开始寻找,如果满足up(q[head+1],q[head])/down(q[head+1],q[head])<=sum[i]则说明q[head+1]的点优于q[head]点,直接跳过
    65             while(head+1<tail&&up(q[head+1],q[head])<=sum[i]*down(q[head+1],q[head]))head++;
    66             dp[i]=dp[q[head]]+(sum[i]-sum[q[head]])*((sum[i]-sum[q[head]]))+m;
    67             //新加入的i点可能与原来单调队列中的点形成上凸折线,所以需要把那些形成上凸折线的点剔除掉。
    68             //即如果k(i,q[tail-1])<k(q[tail-1],q[tail-2]),则形成上凸折线,q[tail-1]该点必须剔除。
    69             //最后再把i点加入单调队列。
    70             while(head+1<tail&&up(q[tail-1],q[tail-2])*down(i,q[tail-1])>=down(q[tail-1],q[tail-2])*up(i,q[tail-1]))tail--;
    71             q[tail++]=i;
    72         }
    73         cout<<dp[n]<<endl;
    74     }
    75     return 0;
    76 #ifdef Local
    77     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    78 #endif
    79 }
  • 相关阅读:
    判断ArryaList有没有重复对象的方法
    使用Java对字符串进行升序排序
    用三层盒子结构实现多边框
    盒子模型的margin负数用法
    解决盒子浮动时margin会显示两倍的美观问题
    纯HTML和CSS实现JD轮播图
    Java的策略模式
    Java的适配器模式
    Java的单例模式
    阿里云服务器配置
  • 原文地址:https://www.cnblogs.com/27sx/p/6875418.html
Copyright © 2011-2022 走看看