2.聪明的质监员(qc.cpp/c/pas) 
【问题描述】 
小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1
到 n 逐一编号,每个矿石都有自己的重量 wi 以及价值 vi。检验矿产的流程是: 
1、给定 m个区间[Li,Ri]; 
2、选出一个参数 W; 
3、对于一个区间[Li,Ri],计算矿石在这个区间上的检验值 Yi  : 
 j∈[Li ,Ri ]且wj ≥W ,j 是矿石编号 

这批矿产的检验结果 Y为各个区间的检验值之和。即:  

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

【输入】 
输入文件 qc.in。 
第一行包含三个整数 n,m,S,分别表示矿石的个数、区间的个数和标准值。 
接下来的 n行,每行 2个整数,中间用空格隔开,第 i+1 行表示 i 号矿石的重量 wi 和价
值 vi  。 
接下来的 m行,表示区间,每行 2个整数,中间用空格隔开,第 i+n+1 行表示区间[Li, 
Ri]的两个端点 Li 和 Ri。注意:不同区间可能重合或相互重叠。 
【输出】 
输出文件名为 qc.out。 
输出只有一行,包含一个整数,表示所求的最小值。 

【输入输出样例】 
qc.in 
5 3 15  
1 5   
2 5 
3 5 
4 5 
5 5 
1 5 
2 4 
3 3 
qc.out 
10 

【输入输出样例说明】 
当 W 选 4 的时候,三个区间上检验值分别为 20、5、0,这批矿产的检验结果为 25,此
时与标准值 S相差最小为 10。 
【数据范围】 
对于 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≤10^6,0<S≤10^12,1≤Li≤Ri≤n。

题解:很容易发现W越大,Y越小,具有单调性,可以用二分来计算;

这里求区间内的大于W的个数乘wj大于W的石头的v的和的积,这玩意是可以用前缀和优化的;

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#include<map>
#include<set>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
using namespace std;
#define LL long long
#define up(i,j,n) for(int i=(j);(i)<=(n);(i)++)
#define max(x,y) ((x)<(y)?(y):(x))
#define min(x,y) ((x)<(y)?(x):(y))
#define FILE "1"
namespace OI{
const int maxn=;
const LL inf=1000000000000000000LL;
int w[maxn],v[maxn],q[maxn];
LL ws[maxn],vs[maxn],S;
int n,m,cnt=;
int b[maxn][];
void init(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
scanf("%d%d%I64d",&n,&m,&S);
up(i,,n)scanf("%d%d",&w[i],&v[i]);
up(i,,m)scanf("%d%d",&b[i][],&b[i][]);
up(i,,n)q[++cnt]=w[i];q[++cnt]=;
sort(q+,q+cnt+);
}
LL ans=inf;
bool get(int mid){
memset(vs,,sizeof vs);
memset(ws,,sizeof ws);
up(i,,n){
vs[i]=vs[i-];ws[i]=ws[i-];
if(w[i]>=q[mid])vs[i]+=v[i],ws[i]+=;
}
LL Y=;
up(i,,m){
Y+=(ws[b[i][]]-ws[b[i][]-])*(vs[b[i][]]-vs[b[i][]-]);
if(Y<)return ;//有可能爆LL,爆掉时,很显然不可能是最优解,直接退出即可;
}
if(abs(Y-S)<=ans)ans=abs(Y-S);
return Y>=S;
}
void slove(){
init();
int left=,right=cnt,mid;
while(left+<right){
mid=(left+right)>>;
if(get(mid))left=mid;
else right=mid;
}
get(left);get(right);
cout<<ans<<endl;
}
} int main(){
using namespace OI;
slove();
}

最新文章

  1. Python subprocess.Popen communicate() 和wait()使用上的区别
  2. Linux 基本命令
  3. Snort 安装 配置 - Archlinux
  4. Code::Blocks配置GTK+2和GTK+3
  5. Effective Objective-C 2.0 学习记录
  6. Quartz使用总结
  7. http返回状态代码及含义
  8. 游戏开发设计模式之对象池模式(unity3d 示例实现)
  9. Pro Android 4 第六章 构建用户界面以及使用控件(一)
  10. In Action(最短路+01背包)
  11. PHP 引用是个坑,请慎用
  12. 如何设置非管理员用户配置特定的IIS站点
  13. Unity3D UGUI实现Toast
  14. DDD实战进阶第一波(三):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架二)
  15. linux下查看运行进程详细信息
  16. 【转】Andorid中Intent的使用-返回数据给上一个活动
  17. php的opcode缓存
  18. Tcpdump 的用法
  19. tortoiseSVN 合并代码方法
  20. Missing artifact jdk.tools:jdk.tools:jar:1.8 pom.xml

热门文章

  1. Tyvj——P1952 Easy
  2. Wireshark如何选择多行
  3. PHP运行环境搭建
  4. PyTorch学习笔记之DataLoaders
  5. hdu 4300 Clairewd’s message(具体解释,扩展KMP)
  6. 采用scp命令在Linux系统之间copy文件
  7. HDU 4635 Strongly connected(强连通)经典
  8. Use the command of tar to multi-part archive method.
  9. C结构体对齐
  10. Numpy数组计算