zoukankan      html  css  js  c++  java
  • bzoj1044[HAOI2008]木棍分割



    Description

    有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007。。。

    Input

    输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍的长度.

    Output

    输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.

    Sample Input

    3 2
    1
    1
    10

    Sample Output

    10 2

    两种砍的方法: (1)(1)(10)和(1 1)(10)
    数据范围
    n<=50000, 0<=m<=min(n-1,1000).
    1<=Li<=1000.

    一开始以为是水题……结果斯巴达了三个小时才调出来……

    第一问是求最小值,而且最大值最小,显然二分。就是枚举木棍的总长度最大值,然后判定。效率O(nlog(max(sum[n]))),其中sum[i]为前缀和。

    第二问超坑……设f[i][j]为分成i段,枚举前j根木棍,每段长度都不大于第一问ans的方案数。f[i][j]=Σf[i-1][k],其中k满足sum[k]-s[j-1]<=ans,即最后一段区间总长(j)不超过最大值。这样暴力枚举效率O(n^2m)会T。但是发现转移的Σf[i-1][k]可以通过维护一个队列保存当前的k来O(1)算出来。然后又发现直接开5千万的数组要做死,还要用滚动数组……

    #include<cstdio>
    #include<cstring>
    #define maxn 100001
    #define mod 10007
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    int n,m;
    int a[maxn];
    int s[maxn];
    int q[maxn];
    int f[2][maxn];
    int l,r,ans,ans2;
    inline bool mark(int k)
    {
    int sum,piece=m,now=1;
    while (piece&&now<=n)
    {
    sum=0;
    while (now<=n&&sum+a[now]<=k) sum+=a[now++];
    piece--;
    }
    if (now<=n&&s[n]-s[now-1]>k) return 0;
    return 1;
    }
    inline void init()
    {
    n=read();
    m=read();
    for (int i=1;i<=n;i++) 
    {
    a[i]=read();
    s[i]=s[i-1]+a[i];
    if (a[i]>l) l=a[i];
    }
    r=s[n];
    }
    inline void bsearch(
    {
    while (l<=r)
    {
    int mid=(l+r)>>1;
    if (mark(mid)){ans=mid;r=mid-1;}
    else l=mid+1;
    }
    printf("%d ",ans);
    
    }
    inline void dp()
    {
    f[0][0]=1;
    int pre,cur,res;
    for (int i=1;i<=m;i++)
    {
    pre=i&1;
    cur=pre^1;
    int h=1,t=1;
    q[1]=0;res=f[cur][0];
    for (int j=1;j<=n;j++)
     {
      while (h<=t&&s[j]-s[q[h]]>ans)
      {
      res=(res-f[cur][q[h++]])%mod;
      res=(res+mod)%mod;
      }
      f[pre][j]=res;
      q[++t]=j;res=(res+f[cur][j])%mod;
     }
    for (int j=n-1;j>0;j--)
    {
    if (s[n]-s[j]>ans) break;
    ans2=(ans2+f[pre][j])%mod;
    }
    memset(f[cur],0,sizeof f[cur]);
    }
    printf("%d
    ",ans2);
    }
    int main()
    {
    init();
    bsearch();
    dp();
    }
    ——by zhber,转载请注明来源
  • 相关阅读:
    (82)zabbix如何选择适合的监控类型
    (80)zabbix性能优化中的几个建议
    (79)zabbix key总是not supported的解决方法
    (78)zabbix值缓存(value cache)说明
    Centos7搭建docker仓库
    centos7安装docker
    Win10调整MTU值
    nginx配置ssl证书
    CentOS7.6配置do.cker和K.B.S
    RAID阵列盘有一块状态变为外来处理方法
  • 原文地址:https://www.cnblogs.com/zhber/p/4036045.html
Copyright © 2011-2022 走看看