博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CodeVS 1138-聪明的质检员
阅读量:5338 次
发布时间:2019-06-15

本文共 2190 字,大约阅读时间需要 7 分钟。

原题

题目描述 Description

小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从1到n逐一编号,每个矿石都有自己的重量wi以及价值vi.检验矿产的流程是:见图
若这批矿产的检验结果与所给标准值S相差太多,就需要再去检验另一批矿产.小T不想费时间去检验另一批矿产,所以他想通过调整参数W的值,让检验结果尽可能的靠近标准值S,即使得S-Y的绝对值最小.请你帮忙求出这个最小值.

输入描述 Input Description

第一行包含三个整数n,m,S,分别表示矿石的个数、区间的个数和标准值.

接下来的 n 行,每行2个整数,中间用空格隔开,第i+1行表示i号矿石的重量wi和价值vi.
接下来的 m 行,表示区间,每行2个整数,中间用空格隔开,第i+n+1 行表示区间[Li,Ri]的两个端点Li 和Ri.注意:不同区间可能重合或相互重叠.

输出描述 Output Description

输出只有一行,包含一个整数,表示所求的最小值.

样例输入 Sample Input

5 3 15

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

样例输出 Sample Output

10

提示 Hint

当 W 选4 的时候,三个区间上检验值分别为20、5、0,这批矿产的检验结果为25,此时与标准值S 相差最小为10.

 数据范围 Data Size

对于 10%的数据,有1≤n,m≤10;

对于 30%的数据,有1≤n,m≤500;
对于 50%的数据,有1≤n,m≤5,000;
对于 70%的数据,有1≤n,m≤10,000;
对于 100%的数据,有1≤n,m≤200,000,0 < wi, vi≤106,0 < S≤1012,1≤Li≤Ri≤n. 

 

题意

给出n个物品的重量w[i]和价值v[i],以及一个标准值S,并给出m个[l[i],r[i]]的区间.要求你找出一个数K,每次求出l[i]~r[i]的区间中,w[j]≥K{l[i]≤j≤r[i]}的物品总数以及每个物品相对应的价值,并将价值全部相加,再将两者相乘,乘积为X[i],最后将m个X[i]相加得到P,使得abs(P-S)最小,并输出abs(P-S).

题解

首先二分K值,每次求出当参数=K时的检验结果与S的差,K的最大值为max(w[i]).

当样例的K分别等于{1,2,3,4,5,6}时,检验结果与S的差的绝对值分别为{160,115,55,10,10,15},设此序列为a[i].但是要怎么通过二分求出这个有序的单峰序列中最小的数呢?

我们可以先不考虑绝对值的情况,即原序列变为{160,115,55,10,-10,-15},这样便成了一个有序的下降序列,然后二分出大于等于0的最小值的位置.通过查找,我们发现这个序列二分后的答案为4,即序列中的10.

设p为现在二分后的答案4,则最终的答案ans=min(a[p],a[p+1]).因为我们二分出来的p值已经是正数这一边的绝对值最小值的位置,那我们只要让它与负数的绝对值最小值比较,最后输出较小的那个就好了.

然后记得每次二分都要O(n)维护两个前缀和,一个表示[1,i]的区间内有多少个w值是≥K的,另一个表示[1,i]的区间内的v值总和.

代码如下:

 

uses math;var w,ww,v,vv,l,r:array[0..200000] of int64; var ll,rr,mid,maxw,n,m,s,pp,ans:int64;var i:longint;function check(x:int64):int64;var sum:int64;var i:longint;begin  sum:=0;  for i:=1 to n do  begin    ww[i]:=0;vv[i]:=0;    if w[i]>=x then    begin      ww[i]:=ww[i-1]+1;      vv[i]:=vv[i-1]+v[i];    end else begin ww[i]:=ww[i-1];vv[i]:=vv[i-1]; end;  end;  for i:=1 to m do sum:=(vv[r[i]]-vv[l[i]-1])*(ww[r[i]]-ww[l[i]-1])+sum;  exit(sum-s);end;begin  readln(n,m,s);maxw:=-maxlongint;  for i:=1 to n do begin readln(w[i],v[i]);maxw:=max(maxw,w[i]); end;  for i:=1 to m do readln(l[i],r[i]);  rr:=maxw+1;ll:=1;  while ll+1
>1; if check(mid)>0 then ll:=mid else rr:=mid; end; ans:=min(abs(check(ll)),abs(check(ll+1))); writeln(ans);end.

转载于:https://www.cnblogs.com/HAdolf-HQY/p/6412051.html

你可能感兴趣的文章
把word文档中的所有图片导出
查看>>
ubuntu 18.04取消自动锁屏以及设置键盘快捷锁屏
查看>>
arcgis api 4.x for js 结合 Echarts4 实现散点图效果(附源码下载)
查看>>
YTU 2625: B 构造函数和析构函数
查看>>
加固linux
查看>>
Hyper-V虚拟机上安装一个图形界面的Linux系统
查看>>
【Crash Course Psychology】2. Research & Experimentation笔记
查看>>
关于 linux 的 limit 的设置
查看>>
MTK笔记
查看>>
【题解】 bzoj1597: [Usaco2008 Mar]土地购买 (动态规划+斜率优化)
查看>>
fat32转ntfs ,Win7系统提示对于目标文件系统文件过大解决教程
查看>>
shell cat 合并文件,合并数据库sql文件
查看>>
python全栈 计算机硬件管理 —— 硬件
查看>>
Delphi7编译的程序自动中Win32.Induc.a病毒的解决办法
查看>>
egret3D与2D混合开发,画布尺寸不一致的问题
查看>>
struts1和struts2的区别
查看>>
Redis常用命令
查看>>
2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)
查看>>
微软职位内部推荐-Sr. SE - Office incubation
查看>>
C#类与结构体究竟谁快——各种函数调用模式速度评测
查看>>