• bzoj1044


    好题

    第一问不难,毕竟二分答案类的题目在USACO上都练了好多遍了

    第二问充分的暴露了我dp渣的本性

    一开始楞是没想出来

    f[i,j]表示到第i根木棒切了j刀满足最长段小于等于ans的方案数

    式子是这样的f[i,j]=sigma(f[k,j-1]) if sum[i]-sum[k]<=ans

    然后发现我的优化水平还是不错的,

    首先是空间上的问题,观察得知,切这刀的方案数只与切前一刀有关,于是我们滚动数组

    再看时间,观察k的选取,与这是第几刀无关

    再看,如果满足sum[i]-sum[k]<=ans 那么k~i-1一定都是符合的切法

    于是我们预先处理一下即可

    复杂度为O(nlogn+mn)

     1 const mo=10007;
     2 var f:array[0..1,0..50010] of longint;
     3     sum,s,a,b:array[0..50010] of longint;
     4     p,l,r,mid,n,m,i,j,t,ans:longint;
     5 
     6 function check(s:longint):boolean;
     7   var t,len,i:longint;
     8   begin
     9     t:=0;
    10     len:=0;
    11     p:=0;
    12     for i:=1 to n do
    13       if len+a[i]>s then
    14       begin
    15         inc(t);
    16         if t>m then exit(false);
    17         if len>p then p:=len;
    18         len:=a[i];
    19       end
    20       else len:=len+a[i];
    21     if len>p then p:=len;
    22     exit(true);
    23   end;
    24 begin
    25   readln(n,m);
    26   for i:=1 to n do
    27   begin
    28     readln(a[i]);
    29     sum[i]:=sum[i-1]+a[i];
    30     if l<a[i] then l:=a[i];
    31   end;
    32   r:=sum[i];
    33   while l<=r do     //二分答案
    34   begin
    35     mid:=(l+r) shr 1;
    36     if check(mid) then
    37     begin
    38       ans:=p;
    39       r:=p-1;
    40     end
    41     else l:=mid+1;
    42   end;
    43   for i:=1 to n do
    44     if sum[i]<=ans then f[0,i]:=1 else break;
    45   j:=0;
    46   for i:=1 to n do  //预处理
    47   begin
    48     while sum[i]-sum[j]>ans do inc(j);
    49     b[i]:=j;
    50   end;
    51   p:=0;
    52   t:=f[p,n];
    53   for i:=1 to m do
    54   begin
    55     p:=1-p;
    56     fillchar(s,sizeof(s),0);
    57     for j:=1 to n do
    58     begin
    59       if b[j]-1>0 then r:=b[j]-1 else r:=0; //小细节
    60       f[p,j]:=(s[j-1]-s[r]+mo) mod mo;
    61       s[j]:=(s[j-1]+f[1-p,j]) mod mo;
    62     end;
    63     t:=(t+f[p,n]) mod mo;
    64   end;
    65   writeln(ans,' ',t);
    66 end.
    View Code
  • 相关阅读:
    Class StatusesTableSeeder does not exist 如何解决
    Heroku 如何上重置 PostgreSQL 数据库
    git强制push
    Heroku登录失败
    将手机替换为*号
    使用TP自带缓存时。出现第一次拿不到数据。
    PHP实现查看邮件是否被阅读
    使用file_get_contents下载图片
    介绍几款开源好用的产品
    查看光纤卡wwn号【转载】
  • 原文地址:https://www.cnblogs.com/phile/p/4473237.html
Copyright © 2020-2023  润新知