【洛谷p1314】聪明的质监员
有关算法:
二分答案;
但是你只二分答案是不够的,因为你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】聪明的质监员的更多相关文章
- 洛谷P1314 聪明的质监员
P1314 聪明的质监员 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi .检验矿产的流程是: ...
- 洛谷P1314 聪明的质监员 题解
题目 聪明的质监员 题解 这道题和之前Sabotage G的那道题类似,都是用二分答案求解(这道题还要简单一些,不需要用数学推导二分条件,只需简单判断一下即可). 同时为了降低复杂度,肯定不能用暴力求 ...
- 洛谷 P1314 聪明的质监员 —— 二分
题目:https://www.luogu.org/problemnew/show/P1314 显然就是二分那个标准: 当然不能每个区间从头到尾算答案,所以要先算出每个位置被算了几次: 不知为何自己第一 ...
- [NOIP2011] 提高组 洛谷P1314 聪明的质监员
题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi .检验矿产的流程是: 1 .给定m 个区间[L ...
- 洛谷 P1314 聪明的质监员【二分+前缀和】
真是zz, 题目很显然是二分W,然后判断,我一开始是用线段树维护当前w[i]>W的个数和v(公式就是区间满足要求的个数*满足要求的v的和),然后T成70 后来想到树状数组差分常数或许会小,于是改 ...
- 洛谷——P1314 聪明的质监员
https://www.luogu.org/problem/show?pid=1314 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每 ...
- 『题解』洛谷P1314 聪明的质监员
更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Portal3: Vijos Description 小T是一名质量监督员,最近负责检验一批矿产的质量.这 ...
- 洛谷 [P1314] 聪明的质检员(NOIP2011 D2T2)
###一道二分答案加前缀和### 题目中已经暗示的很明显了 "尽可能靠近" " 最小值" 本题的主要坑点在于 long long 的使用 ##abs函数不支持l ...
- P1314 聪明的质监员(前缀和+二分)
P1314 聪明的质监员 显然可以二分参数W 统计Y用下前缀和即可. #include<iostream> #include<cstdio> #include<cstri ...
- luogu P1314 聪明的质监员 x
P1314 聪明的质监员(至于为什么选择这个题目,可能是我觉得比较好玩呗) 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自 ...
随机推荐
- spring jpa 带参数分页查询(一)
1.写个接口继承JpaRepository @NoRepositoryBean public interface BaseRepository<T,PK extends Serializable ...
- 【LuoguP2792 】[JSOI2008]小店购物(最小树形图)
题目链接 题目描述 小店的优惠方案十分简单有趣: 一次消费过程中,如您在本店购买了精制油的话,您购买香皂时就可以享受2.00元/块的优惠价:如果您在本店购买了香皂的话,您购买可乐时就可以享受1.50元 ...
- 对Moment.js的研究
创建npm install moment --save-dev 日期格式化 moment().format('MMMM Do YYYY, h:mm:ss a'); // 六月 4日 2019, 6:2 ...
- springboot自定义错误页
静态错误页放在 动态可以放在freemaker或者thymeleaf 匹配规则: 先找动态页面再找静态页面 先找精确错误页面再找模糊页面 注:精确错误页面=50 ...
- mysql RIGHT JOIN关键字 语法
mysql RIGHT JOIN关键字 语法 作用:RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行.惠州大理石 ...
- BZOJ 5129: [Lydsy1712月赛]树上传送 点分树+Dijkstra
Description http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf Input Output 暑假集训的时候点分树做的比较少,所 ...
- 正则表达式小结,数据预处理中常用的shell命令
数据预处理中,这部分命令非常有用. 不需要编写代码,直接通过shell脚本通常就能修改文件格式.有时候sed和awk联合几乎能实现所有功能. 管道命令 | 重定向命令>,2>,>&g ...
- 微信小程序之登录用户不是该小程序的开发者
当uniapp项目转为小程序项目的时候,预览会显示“您不是登录用户...”,所以没有办法发布,这个时候打开“project.config.json”设置一下appid,与你公众号appid一致就可以
- 前端进阶系列(二):css常见布局解决方案
水平居中布局 margin+定宽 <div class="parent"> <div class="child">Demo</di ...
- php中钩子(hook)的应用示例demo
我们先来回顾下原本的开发流程:产品汪搞出了一堆需求:当用户注册成功后需要发送短信.发送邮件等等:然后聪明机智勇敢的程序猿们就一扑而上:把这些需求转换成代码扔在 用户注册成功 和 跳转到首页 之间: 没 ...