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

    1044: [HAOI2008]木棍分割

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1580  Solved: 567
    [Submit][Status]

    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.

    HINT

     

    Source

    题解:

    第一问二分+贪心可以得出

    第二份朴素的话最坏情况下是O(mn^2)的,但考虑到每一个接点有pre[i],表示满足s[i]-s[j]<=ans的最大j,这样转移的时候

    有f[i,j]=sigma(f[k,j-1])(pre[i]<=k<=i-1),考虑到pre[i]是单增的的,所以我们可以用单调队列来搞,优化到O(mn),不过也可以不用队列,

    只用一个临时变量来记录当前时刻有用的节点的权值和

    下面说一些题外话:

    1.感觉此题很难写

    2.写程序的时候,一要易懂,不容易出错,而才是简短,优美,不要一上来就想着可以怎么怎么减少代码,否则会把自己搞晕

    代码:

     1 const maxn=50000+100;p=10007;
     2 var i,j,n,m,x,ans,cnt,l,r,mid,t,sum:longint;
     3     q,pre,len,s:array[0..maxn] of longint;
     4     f:array[0..maxn,0..1] of longint;
     5 procedure init;
     6  begin
     7   readln(n,m);
     8   for i:=1 to n do begin readln(len[i]);s[i]:=s[i-1]+len[i];end;
     9   s[n+1]:=maxlongint;
    10  end;
    11 function test(x:longint):boolean;
    12  var i,j,sum:longint;
    13  begin
    14   sum:=0;j:=0;
    15   for i:=1 to n do
    16    if sum+len[i]<=x then inc(sum,len[i])
    17    else begin inc(j);sum:=len[i];end;
    18  exit(j<=m);
    19  end;
    20 procedure main;
    21  begin
    22   l:=0;r:=1000000000;
    23   while l<r do
    24    begin
    25      mid:=(l+r)>>1;
    26      if test(mid) then r:=mid else l:=mid+1;
    27    end;
    28   ans:=l;
    29   j:=0;
    30   for i:=1 to n do
    31    begin
    32    while s[i]-s[j]>ans do inc(j);
    33    pre[i]:=j;
    34    end;
    35   fillchar(f,sizeof(f),0);
    36   i:=1;while s[i]<=ans do begin f[i,0]:=1;inc(i);end;
    37   t:=0;cnt:=0;
    38   for i:=1 to m do
    39    begin
    40     t:=1-t;
    41     l:=0;r:=0;sum:=0;
    42     for j:=1 to n do
    43      begin
    44      while (l<r) and (q[l]<pre[j]) do begin sum:=(sum-f[q[l],1-t]+p) mod p;inc(l);end;
    45      f[j,t]:=sum;
    46      inc(r);q[r]:=j;sum:=(sum+f[q[r],1-t]) mod p;
    47      end;
    48     cnt:=(cnt+f[n,t]) mod p;
    49    end;
    50  writeln(ans,' ',cnt);
    51  end;
    52 begin
    53   assign(input,'input.txt');assign(output,'output.txt');
    54   reset(input);rewrite(output);
    55   init;
    56   main;
    57   close(input);close(output);
    58 end.  
    View Code
  • 相关阅读:
    ORA12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
    ORACLE MERGE 介绍
    【转】三大UML建模工具Visio、Rational Rose、PowerDesign的区别
    ORALC的STDDEV、STDDEV_POP、STDDEV_SAMP等函数
    SQL语言艺术实践篇——局外思考
    数据分析方法
    ORACLE FLASHBACK TABLE 的一个有趣问题
    avalon有关ViewModel与Model的同步问题
    迷你MVVM框架 avalonjs 0.73发布
    将一个节点集合以最少的步骤转换为另一个节点集合
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3916945.html
Copyright © 2011-2022 走看看