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("\n");
58     for (int i = l;i <= r;i++) printf("%d ",que[i]);
59     printf("\n");
60     for (int i = 1;i <= n;i++) printf("%d ",f[i]);
61     printf("\n");
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\n",f[n]);
82     return 0;
83 }
View Code

 

posted @ 2014-01-06 13:14  乌拉拉979  阅读(215)  评论(0编辑  收藏  举报