聪明的质监员【题目链接】

有关算法:

二分答案;

但是你只二分答案是不够的,因为你check会炸,所以还要考虑前缀和;

首先假装我们的check已经写好了,main函数:

int main() {
n=read();
m=read();
S=read();
ll maxn=;
for(ll i=; i<=n; i++)
w[i]=read(),v[i]=read(),maxn=max(maxn,w[i]);
for(ll i=; i<=m; i++)
_l[i]=read(),_r[i]=read();
ll l=,r=maxn,ans1=1e17+,ans2=1e17+;
while(l<=r) {
ll mid=l+r>>;
ll ls=check(mid);
if(ls<S) {
ans1=min(ans1,S-ls);
r=mid-;
}
if(ls==S) {
printf("");
return ;
}
if(ls>S) {
ans2=min(ans2,ls-S);
l=mid+;
}
}
printf("%lld",min(ans1,ans2));
return ;
}

输入没有什么可以说的,然后是二分答案,二分答案的话,从0~最大的wi;

二分的标准套路,先计算mid,用check函数判应该往左区间二分还是右区间二分,比较不好想的就是怎么判断往左区间还是右区间二分,这里可以想到,当我们求出的中间值的Y之后,如果发现它比S小,那么如果要找更小的差距,应该让Y的值更大才有可能,那么如果让Y的值更大,我们应该选入更多的矿产,所以我们应该使二分的答案减小,因此r=mid-1;然后这里记录两个答案,ans1,ans2,分别记录的是求得的值小于S的最小差,求得值大于S的最小差(显然等于S时就直接输出不需要再继续循环了);

然后如果没有找到使差为0的W,我们就输出ans1和ans2中较小的一个;

好了讲完了;

并没有讲完啊,我们还莫得讲check函数;

最简单的方法,暴力扫描:

ll check(ll x) {
ll cnt=,sum=,Y=;
for(ll i=; i<=m; i++) {
cnt=;
sum=;
for(ll j=_l[i]; j<=_r[i]; j++) {
if(w[j]>=x) cnt++,sum+=v[j];
}
Y+=(cnt*sum);
}
return Y;
}

然后你会发现你T成这样:

然后经过大佬ych的提醒,我们想到了前缀和:

ll check(ll x) {
ll Y=;
for(int i=;i<=n;i++){
if(w[i]>=x) sum[i]=sum[i-]+v[i],cnt[i]=cnt[i-]+;
else sum[i]=sum[i-],cnt[i]=cnt[i-];
}
for(int i=;i<=m;i++){
Y+=_abs(sum[_r[i]]-sum[_l[i]-])*_abs(cnt[_r[i]]-cnt[_l[i]-]);
}
return Y;
}

sum[i]表示1~i所有点中所有wi>=二分答案的的矿产的v之和,cnt[i]表示1~i以内所有点中所有wi>=二分答案的矿产个数;

然后处理应该很好理解,不再赘述;

然后再一次for循环,对于每个区间,利用维护的前缀和计算sum*cnt,然后相加即为答案;

#include<bits/stdc++.h>
#define ll long long using namespace std; inline ll read() {
ll ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} ll n,m,w[],v[],S,_l[],_r[],sum[],cnt[]; ll _abs(ll x) {
if(x<) x=-x;
return x;
} ll check(ll x) {
ll Y=;
for(int i=;i<=n;i++){
if(w[i]>=x) sum[i]=sum[i-]+v[i],cnt[i]=cnt[i-]+;
else sum[i]=sum[i-],cnt[i]=cnt[i-];
}
for(int i=;i<=m;i++){
Y+=_abs(sum[_r[i]]-sum[_l[i]-])*_abs(cnt[_r[i]]-cnt[_l[i]-]);
}
return Y;
} int main() {
n=read();
m=read();
S=read();
ll maxn=;
for(ll i=; i<=n; i++)
w[i]=read(),v[i]=read(),maxn=max(maxn,w[i]);
for(ll i=; i<=m; i++)
_l[i]=read(),_r[i]=read();
ll l=,r=maxn,ans1=1e17+,ans2=1e17+;
while(l<=r) {
ll mid=l+r>>;
ll ls=check(mid);
if(ls<S) {
ans1=min(S-ls,ans1);
r=mid-;
}
if(ls==S) {
printf("");
return ;
}
if(ls>S) {
ans2=min(ans2,ls-S);
l=mid+;
}
}
printf("%lld",min(ans1,ans2));
return ;
}

end-

【洛谷p1314】聪明的质监员的更多相关文章

  1. 洛谷P1314 聪明的质监员

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

  2. 洛谷P1314 聪明的质监员 题解

    题目 聪明的质监员 题解 这道题和之前Sabotage G的那道题类似,都是用二分答案求解(这道题还要简单一些,不需要用数学推导二分条件,只需简单判断一下即可). 同时为了降低复杂度,肯定不能用暴力求 ...

  3. 洛谷 P1314 聪明的质监员 —— 二分

    题目:https://www.luogu.org/problemnew/show/P1314 显然就是二分那个标准: 当然不能每个区间从头到尾算答案,所以要先算出每个位置被算了几次: 不知为何自己第一 ...

  4. [NOIP2011] 提高组 洛谷P1314 聪明的质监员

    题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi .检验矿产的流程是: 1 .给定m 个区间[L ...

  5. 洛谷 P1314 聪明的质监员【二分+前缀和】

    真是zz, 题目很显然是二分W,然后判断,我一开始是用线段树维护当前w[i]>W的个数和v(公式就是区间满足要求的个数*满足要求的v的和),然后T成70 后来想到树状数组差分常数或许会小,于是改 ...

  6. 洛谷——P1314 聪明的质监员

    https://www.luogu.org/problem/show?pid=1314 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每 ...

  7. 『题解』洛谷P1314 聪明的质监员

    更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Portal3: Vijos Description 小T是一名质量监督员,最近负责检验一批矿产的质量.这 ...

  8. 洛谷 [P1314] 聪明的质检员(NOIP2011 D2T2)

    ###一道二分答案加前缀和### 题目中已经暗示的很明显了 "尽可能靠近" " 最小值" 本题的主要坑点在于 long long 的使用 ##abs函数不支持l ...

  9. P1314 聪明的质监员(前缀和+二分)

    P1314 聪明的质监员 显然可以二分参数W 统计Y用下前缀和即可. #include<iostream> #include<cstdio> #include<cstri ...

  10. luogu P1314 聪明的质监员 x

    P1314 聪明的质监员(至于为什么选择这个题目,可能是我觉得比较好玩呗) 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自 ...

随机推荐

  1. kettle imestamp : Unable to get timestamp from resultset at index 22

    在做ETL的时候,连接MySQL读取含有timestamp类型的表,出现如下错误: 经Google,据说是MySQL自身的问题.解决方法也很简单,在Spoon的数据库连接中,打开选项,加入一行命令参数 ...

  2. Java课后作业04

    一.古罗马皇帝凯撒在打仗时曾经加密军事情报: 1.设计思想: 加密原理是abc等全部后移3位xyz分别等于abc,根据ascii码表的转化,将其利用charat()取单个字符进行转化,再利用Strin ...

  3. 【05】Python 标准模块:random、os、time、hashlib 第三方模块:excel、数据库 列表生成式

    1 模块分类 标准模块,不需要你单独安装,python自带的模块 第三方模块 自己写的python 一个python文件就是一个模块 2 random模块 2.1 随机取元素 import rando ...

  4. lambda匿名函数sorted排序函数filter过滤函数map映射函数

    lambda函数:表示匿名函数,不需要def来声明,一句话就能搞定. 语法:函数名=lamda 参数:返回值 求10的10次方 f=lambda n:n**n print(f(10)) 注意: 函数名 ...

  5. 【牛客Wannafly挑战赛23】F 计数

    题目链接 题意 给定一张边带权的无向图,求生成树的权值和是 k 的倍数的生成树个数模 p 的值. \(n\leq 100,k\leq 100,p\mod k=1\) Sol 看见整除然后 \(p\mo ...

  6. linux运维、架构之路-禅道环境搭建

    一.介绍            禅道项目管理软件是国产的开源项目管理软件,专注研发项目管理,内置需求管理.任务管理.bug管理.缺陷管理.用例管理.计划发布等功能,实现了软件的完整生命周期管理. 禅道 ...

  7. css3圆角边框

    圆角边框 一.border-radius属性简介   为元素添加圆角边框,可以对元素的四个角进行圆角设置(属性不具有继承性) 二.border-radius定义方法 border-radius属性有两 ...

  8. React native 平时积累笔记

    常用插件: react-native-check-box 复选框react-native-sortable-listview 列表拖拽排序 react-native-doc-viewer 预览组件 r ...

  9. word的公式编辑器在插入对象里面!!!!!!!!!!!!!

    word的公式编辑器在  插入->对象  里面!!!!!!!!!!!!!

  10. POJ 3061 Subsequence ( 二分 || 尺取法 )

    题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用 ...