bzoj 1044: [HAOI2008]木棍分割

2016-06-20

第一问是个二分的经典入门题

第二问很容易发现一个DP f[i][j]前i个木棍分j次合法方案数,f[i][j]=f[k][j-1]+...+f[i-1][j-1]; 但这样时间复杂度是O(mn^2),空间复杂度是O(mn) 但我们发现对于相同的j随着i的增加,对应的k也增加,那我们可以根据这个单调性,用前缀和来做到转移复杂度为O(1),空间可以用滚动数组来解决,本来我偷懒用short int开数组,不用滚动数组。结果T了一半,早就听说数组大了会使程序变慢,今天我可算知道了,泪。。。。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<queue>
 7 #define M 100008
 8 #define ll long long
 9 #define Mo 10007
10 using namespace std;
11 ll read()
12 {
13     char ch=getchar();
14     ll x=0,f=1;
15     for(;ch<'0'||ch>'9';ch=getchar())
16       if(ch=='-')
17         f=-1;
18     for(;ch>='0'&&ch<='9';ch=getchar())
19       x=x*10+ch-'0';
20     return x*f;
21 }
22 short int f[50010][2];
23 int n,m,a[50009],l,r,ans,b[50009],p=1,q;
24 bool pan(int x)
25 {
26     int q=0,sum=0;
27     for(int i=1;i<=n;i++)
28       {
29           q+=a[i];
30           if(q>x)
31             {
32                 sum++;
33                 q=a[i];
34           }
35       }
36     if(sum<=m)
37       return 1;
38     return 0;
39 }
40 int main()
41 {
42     n=read();
43     m=read();
44     for(int i=1;i<=n;i++)
45       {
46         a[i]=read();
47         l=max(a[i],l);
48         r+=a[i];
49       }
50     for(;l<=r;)
51       {
52           int mid=(l+r)>>1;
53           if(pan(mid))
54             {
55                 ans=mid;
56                 r=mid-1;
57             }
58         else
59           l=mid+1;
60       }
61     printf("%d ",ans);
62     for(int i=1;i<=n;i++)
63       a[i]+=a[i-1];
64     for(int i=1;i<=n;i++)
65       if(a[i]<=ans)
66         f[i][p]=1;
67     int an=f[n][p];
68     for(int i=1;i<=n;i++)
69       b[i]=f[i][p]+b[i-1];
70     for(int i=1;i<=m;i++)
71       {
72           int h=0;
73           for(int j=i+1;j<=n;j++)
74             {
75              for(;a[j]-a[h]>ans;h++);
76              if(h)
77                     f[j][q]=(b[j-1]-b[h-1]+Mo)%Mo;
78              else
79                     f[j][q]=b[j-1]%Mo;
80           }
81         for(int j=1;j<=n;j++)
82            b[j]=f[j][q]+b[j-1];
83         swap(p,q);
84         an=(an+f[n][p])%Mo;
85       }
86     printf("%d\n",an);
87     return

 

posted @ 2016-06-20 20:16  xiw5  阅读(151)  评论(0编辑  收藏  举报