zoukankan      html  css  js  c++  java
  • 聪明的质监员(codevs 1138)题解

    【问题描述】

    小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n 个矿石,从1到n 逐一编号,每个矿石都有自己的重量wi 以及价值vi。检验矿产的流程是:见图

    若这批矿产的检验结果与所给标准值S 相差太多,就需要再去检验另一批矿产。小T不想费时间去检验另一批矿产,所以他想通过调整参数W 的值,让检验结果尽可能的靠近标准值S,即使得S-Y 的绝对值最小。请你帮忙求出这个最小值。

    【样例输入】

        5 3 15
        1 5
        2 5
        3 5
        4 5
        5 5
        1 5
        2 4
        3 3

    【样例输出】

        10

    【解题思路】

        本题为NOIP2011day2第二题,可能很多人不会的原因是因为公式看不懂,先解释一下,Yi的公式是指(符合条件的j的总数)*(vj的和)。现在我们来分析一下题目。题目中说,让我们找一个合适的W的值使得Yi的和与给定的S之差的绝对值最小。由于题目中说j的要求是区间中Wi大于W的矿石,因此,我们可以确定W的范围为minwi-1~maxwi+1。在minwi-1以下的与minwi-1的值相同(全部可以取),同理,maxwi+1以上的与maxwi的值相同(全部不能取)。由于题目中说S-Y的绝对值最小,因此我们可以肯定Y可能>S也可能<S,那么我们将W所可以取的区间二分,如果所得到的Y>S,我们就往右边的区间找,否则往左边的区间找,50分就到手了。

        剩下的50分需要用到一个强大的技巧,也是许多区间问题中非常重要的一个技巧,那就是前缀和。当我们枚举所有矿石中Wi>W的矿石的时候,用一个数组存储,将所有的都算出来,这样,在求某个区间的时候,就只要将右节点的值减去左节点-1的值,即所求的区间了,整个过程是n+m,比m*(r-l)快多了。

    【代码实现】

     1 type rec=record
     2      w,v:int64;
     3 end;
     4 var i,j:longint;
     5     sum,min,w,v,n,m,s,minw,maxw,l,r,mid:int64;
     6     a,b:array[0..200010] of rec;
     7     sumv,sumw:array[0..200010] of int64;
     8 function get(x:int64):int64;
     9 var i,j:longint;
    10 begin
    11  fillchar(sumv,sizeof(sumv),0);
    12  fillchar(sumw,sizeof(sumw),0);
    13  get:=0;
    14  for i:=1 to n do
    15   if a[i].w>x then
    16    begin
    17     sumv[i]:=sumv[i-1]+a[i].v;
    18     sumw[i]:=sumw[i-1]+1;
    19    end
    20   else
    21    begin
    22     sumv[i]:=sumv[i-1];
    23     sumw[i]:=sumw[i-1];
    24    end;
    25  for j:=1 to m do
    26   inc(get,(sumw[b[j].v]-sumw[b[j].w-1])*(sumv[b[j].v]-sumv[b[j].w-1]));
    27 end;
    28 begin
    29  minw:=maxlongint;
    30  readln(n,m,s);
    31  for i:=1 to n do
    32   with a[i] do
    33    begin
    34     readln(w,v);
    35     if w>maxw then
    36      maxw:=w;
    37     if w<minw then
    38      minw:=w;
    39    end;
    40  for i:=1 to m do
    41   with b[i] do
    42    readln(w,v);
    43  l:=minw-1;
    44  r:=maxw+1;
    45  min:=9223372036854775800;
    46  repeat
    47   mid:=(l+r) div 2;
    48   sum:=get(mid);
    49   if abs(sum-s)<min then
    50    min:=abs(sum-s);
    51   if sum>s then
    52    l:=mid+1
    53   else
    54    r:=mid-1;
    55  until l>r;
    56  writeln(min);
    57 end.
  • 相关阅读:
    Drools只执行一个规则或者执行完当前规则之后不再执行其他规则(转)
    使用redis作为缓存,数据还需要存入数据库中吗?(转)
    双亲委派
    SpringBoot整合Mybatis传参的几种方式
    Drool规则引擎详解(转)
    IDEA导出可执行的jar包
    十:SpringBoot-配置AOP切面编程,解决日志记录业务
    九:SpringBoot-整合Mybatis框架,集成分页助手插件
    七:SpringBoot-集成Redis数据库,实现缓存管理
    八:SpringBoot-集成JPA持久层框架,简化数据库操作
  • 原文地址:https://www.cnblogs.com/PengBoLiuXu/p/4538416.html
Copyright © 2011-2022 走看看