山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 1044 [HAOI2008]木棍分割(二分+贪心,DP+优化)

 

【题目链接】

 

    http://www.lydsy.com/JudgeOnline/problem.php?id=1044

 

【题意】

 

    n根木棍拼到一起,最多可以切m刀,问切成后最大段的最小值及其方案数。

 

【思路】

 

    对于第一问可以二分后贪心判断。

    假设第一问得到的答案为L,设f[i][j]前i个木棍切j下且保持段长不超过L的方案数,则有转移式:

        f[i][j]=sigma { f[k][j-1] },k<i,suma(k+1,i)<=L

    优化:

    空间方面可以用个滚动数组。

        时间方面由于前缀和sum是递增的,所以我们拿个指针qf维护一个滑动窗口,使得窗口满足suma<=L,tot顺便记一下和就出来了。

 

【代码】

 

 1 #include<set>
 2 #include<cmath>
 3 #include<queue>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
11 #define rep(a,b,c) for(int a=(b);a>=(c);a--)
12 using namespace std;
13 
14 typedef long long ll;
15 const int N = 1e5+10;
16 const int mod = 1e4+7;
17 
18 ll read() {
19     char c=getchar();
20     ll f=1,x=0;
21     while(!isdigit(c)) {
22         if(c=='-') f=-1; c=getchar();
23     }
24     while(isdigit(c))
25         x=x*10+c-'0',c=getchar();
26     return x*f;
27 }
28 
29 int n,m,ans,a[N],sum[N],f[2][N],cur,q[N],qf,qr;
30 
31 bool can(int M)
32 {
33     int cnt=0,tot=0;
34     FOR(i,1,n) {
35         if(tot+a[i]>M) {
36             if((++cnt)>m) return 0;
37             tot=0;
38         }
39         tot+=a[i];
40     }
41     return 1;
42 }
43 
44 int main()
45 {
46 //    freopen("in.in","r",stdin);
47 //    freopen("out.out","w",stdout);
48     n=read(),m=read();
49     int L=0,R=0;
50     FOR(i,1,n)
51     {
52         a[i]=read(),
53         sum[i]=sum[i-1]+a[i];
54         L=max(L,a[i]);
55     }
56     R=sum[n];
57     while(L<R)
58     {
59         int M=L+R>>1;
60         if(can(M)) R=M; else L=M+1;
61     }
62     printf("%d ",L);
63 
64     FOR(j,0,m)
65     {
66         cur^=1;
67         int tot=0,qf=1;
68         FOR(i,1,n)
69         {
70             if(!j) f[cur][i]=sum[i]<=L;
71             else {
72                 while(qf<i && sum[i]-sum[qf]>L)
73                     tot=(tot-f[cur^1][qf++]+mod)%mod;
74                 f[cur][i]=tot;
75             }
76             tot=(tot+f[cur^1][i])%mod;
77         }
78         ans=(ans+f[cur][n])%mod;
79     }
80     printf("%d\n",ans);
81     return 0;
82 }

 

posted on 2016-04-03 17:10  hahalidaxin  阅读(695)  评论(0编辑  收藏