• 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
    ",ans);
    81     return 0;
    82 }
  • 相关阅读:
    gridview的应用(删除)
    Javascript无刷新TreeView
    利用GridView显示主细表并添加打开、关闭功能
    UpdatePanel 控件简介
    Asp.net中使用fckeditor在线编辑器配置
    C#实现水晶报表绑定数据并实现打印
    Asp.net 2.0 Treeview 动态填充,并实现无限级树
    SQL数据库建表前期优化
    C#发送Email邮件方法总结
    ASP.NET防SQL注入脚本程序
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5350151.html
Copyright © 2020-2023  润新知