# BZOJ 1044 木棍分割

3 2
1
1
10

10 2

## HINT

n<=50000, 0<=m<=min(n-1,1000).

1<=Li<=1000.

## Source

1 #include<cstdio>
2 #include<cstdlib>
3 using namespace std;
4
5 #define rhl 10007
6 #define maxn 50010
7 #define maxm 1010
8
9 int n,m,ans,L[maxn],sum[maxn];
10 short f[maxn][maxm],res[maxn];
11
12 struct node
13 {
14     int a[maxn],*h,*t;
15     node() {h = t = a;}
16
17     inline void push(int k)
18     {
19         *(++t) = k;
20         for (int i = 1;i <= m;++i)
21             (res[i] += f[k][i-1]) %= rhl;
22     }
23
24     inline void pop(int k)
25     {
26         while (sum[k]-sum[*(h+1)] > ans)
27         {
28             for (int i = 1;i <= m;++i)
29                 (res[i] -= f[*(h+1)][i-1]) %= rhl;
30             ++h;
31         }
32     }
33 }team;
34
35 inline bool okay(int l)
36 {
37     int i,j,tot = 0;
38     for (i = 1;i <= n;)
39     {
40         if (tot > m + 1) return false;
41         for (j = i-1;j+1 <= n&&sum[j+1]-sum[i-1] <= l;++j);
42         if (j < i) return false;
43         ++tot; i = j+1;
44     }
45     return tot <= m + 1;
46 }
47
48 inline void dp()
49 {
50     ++m;
51     f[0][0] = 1;
52     team.push(0);
53     for (int i = 1;i <= n;++i)
54     {
55         team.pop(i);
56         for (int j = 1;j <= m;++j) f[i][j] = res[j];
57         team.push(i);
58     }
59     ans = 0;
60     for (int i = 1;i <= m;++i) (ans += f[n][i])%=rhl;
61     ans = ans % rhl + rhl;
62     ans %= rhl;
63 }
64
65 int main()
66 {
67     scanf("%d %d",&n,&m);
68     for (int i = 1;i <= n;++i) scanf("%d",L+i),sum[i] = sum[i-1] + L[i];
69     int l = 1,r = sum[n],mid;
70     while (l <= r)
71     {
72         mid = (l + r) >> 1;
73         if (!okay(mid)) l = mid + 1;
74         else r = mid - 1;
75     }
76     printf("%d ",ans = l);
77     dp();
78     printf("%d",ans);
79     return 0;
80 }
View Code

posted @ 2015-02-16 10:45  lmxyy  阅读(248)  评论(0编辑  收藏