zoukankan      html  css  js  c++  java
  • bzoj 1010: [HNOI2008]玩具装箱toy

    这道题是一道很简单的DP,方程很容易列出来,

    只不过要优化,因为n^2过不了。

    膜拜了一下搞神的《浅析1D1D动态规划的优化(zzx)》

    既可以用斜率优化也可以用单调性优化。

    单调性证明就不说了。

    斜率优化还不太懂所以只写了单调性优化

     1 /*
     2 ID:WULALA
     3 PROB:bzoj1010
     4 LANG:C++
     5 */
     6 #include <cstdio>
     7 #include <cstring>
     8 #include <algorithm>
     9 #include <cmath>
    10 #include <iostream>
    11 #include <ctime>
    12 #include <set>
    13 #define N 50008
    14 #define M
    15 #define mod
    16 #define mid(l,r) ((l+r) >> 1)
    17 #define INF 0x7ffffff
    18 using namespace std;
    19 
    20 int n,L,que[N],st[N],l = 1,r = 1;
    21 long long f[N],pre[N];
    22 inline long long sqr(long long a)
    23 {
    24     return (a*a);
    25 }
    26 
    27 inline long long cal(int s,int t)
    28 {
    29     return (f[s] + sqr(t - s  - 1 + pre[t] - pre[s] - L));
    30 }
    31 
    32 int find(int a)
    33 {
    34     int bot = 1,top = r + 1;
    35     while (bot != top)
    36     {
    37         if (st[que[mid(bot,top)]] > a) top = mid(bot,top);
    38         else bot = mid(bot,top) + 1;
    39     }//寻找第一个比a小可以先找第一个比a大 
    40     return (bot - 1);
    41 }
    42 
    43 int work()
    44 {
    45     memset(que,255,sizeof(que));
    46     que[1] = 0;
    47     st[0] = 1; 
    48     for (int i = 1;i <= n+1;i++) st[i] = n + 1;//方便查找
    49     for (int i = 1;i <= n;i++)
    50     {
    51         f[i] = cal(que[find(i)],i);
    52         while (st[que[r]] > i && r && cal(i,st[que[r]]) < cal(que[r],st[que[r]])) r--;
    53         if (!r)
    54         {
    55             que[++r] = i;
    56             st[i] = i;
    57             continue ;
    58         }
    59         int bot = st[que[r]],top = n + 1;
    60         while (bot != top)
    61         {
    62             if (cal(que[r],mid(bot,top)) >= cal(i,mid(bot,top))) top = mid(bot,top);
    63             else bot = mid(bot,top) + 1;
    64         }
    65         if (bot == n + 1) continue ;//此决策无法入栈
    66         que[++r] = i;
    67         st[i] = bot;
    68     }
    69 }
    70 
    71 int main()
    72 {
    73     scanf("%d%d",&n,&L);
    74     for (int i = 1;i <= n;i++)
    75     {
    76         scanf("%d",&pre[i]);
    77         pre[i] += pre[i-1];
    78     }
    79     work();
    80     printf("%lld",f[n]);
    81     return 0;
    82 }
    View Code

     昨天和洛神聊了下天,把斜率优化学了,顺手写了一下

     1 /*
     2 ID:WULALA
     3 PROB:bzoj1010 slope
     4 LANG:C++
     5 */
     6 #include <cstdio>
     7 #include <cstring>
     8 #include <algorithm>
     9 #include <cmath>
    10 #include <iostream>
    11 #include <ctime>
    12 #include <set>
    13 #define N 50008
    14 #define M
    15 #define mod
    16 #define mid(l,r) ((l+r) >> 1)
    17 #define INF 0x7ffffff
    18 using namespace std;
    19 
    20 int n,L,que[N],l,r;
    21 long long pre[N],f[N];
    22 
    23 inline long long sqr(long long a)
    24 {
    25     return (a*a);
    26 }
    27 
    28 inline long long cal(int s,int t)
    29 {
    30     return (f[s] + sqr(t - s  - 1 + pre[t] - pre[s] - L));
    31 }
    32 
    33 void init()
    34 {
    35     scanf("%d%d",&n,&L);
    36     for (int i = 1;i <= n;i++)
    37     {
    38         scanf("%lld",&pre[i]);
    39         pre[i] += pre[i-1];
    40     }
    41     memset(que,255,sizeof(que));
    42     l = r = que[0] = 0;
    43 }
    44 
    45 long long det(int o,int a,int b)
    46 {
    47     long long xo = pre[o],yo = f[o] + sqr(pre[o]) - 2 * l * pre[o]; 
    48     long long xa = pre[a],ya = f[a] + sqr(pre[a]) - 2 * l * pre[a]; 
    49     long long xb = pre[b],yb = f[b] + sqr(pre[b]) - 2 * l * pre[b];
    50     xa -= xo; xb -= xo;
    51     ya -= yo; yb -= yo;
    52     return (xa * yb - xb * ya); 
    53 }
    54 
    55 void debug()
    56 {
    57     printf("
    ");
    58     for (int i = l;i <= r;i++) printf("%d ",que[i]);
    59     printf("
    ");
    60     for (int i = 1;i <= n;i++) printf("%d ",f[i]);
    61     printf("
    ");
    62 }
    63 
    64 void work()
    65 {
    66     for (int i = 1;i <= n;i++)
    67     {
    68         while (cal(que[l],i) >= cal(que[l+1],i) && que[l+1] != -1) l++;
    69         f[i] = cal(que[l],i);
    70         if (f[i] < 0) printf("error: i");
    71         while (det(que[r-1],que[r],i) < 0 && r > l) r--;
    72         que[++r] = i;
    73 //        debug(); 
    74     }
    75 }
    76 
    77 int main()
    78 {
    79     init();
    80     work();
    81     printf("%lld
    ",f[n]);
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    Python3之format
    xml文件整理
    某系统采集2018
    sublime+python3 中文环境
    python3文本读取与写入常用代码
    redis3.0集群使用发现的一些问题
    mysql字符集
    redis3.0集群搭建
    安装Maven、nexus
    一键安装mysql5.6
  • 原文地址:https://www.cnblogs.com/wulala979/p/3507011.html
Copyright © 2011-2022 走看看