【洛谷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 逐一编号,每个矿石都有自 ...
随机推荐
- BAT面试必问题系列:深入详解JVM 内存区域及内存溢出分析
前言 在JVM的管控下,Java程序员不再需要管理内存的分配与释放,这和在C和C++的世界是完全不一样的.所以,在JVM的帮助下,Java程序员很少会关注内存泄露和内存溢出的问题.但是,一旦JVM发生 ...
- zip(), dict(), itertools.repeat(), list(迭代器)
*. zip(), dict() def demo_zip_dict(): keys = ['a', 'b', 'c'] values = [1, 2, 3] entrys = zip(keys, v ...
- 【LuoguP4916】魔力环
题目链接 题意 求出 \(n\) 个珠子的在旋转同构意义下的手 环 个数,满足以下条件: 恰好有 \(m\) 个黑色珠子,其余为白色. 黑色珠子形成的最长连续段不能超过 \(k\) 个. Sol 考虑 ...
- STM32内部时钟设置-寄存器版
STM32寄存器版本——内部时钟设置 同时要记得把延时初始化函数设置好 //系统时钟初始化函数 //pll:选择的倍频数,从2开始,最大值为16 //pll:选择的倍频数,这里使用内部时钟,PLL为4 ...
- 文本跟随鼠标并且显示x轴和y轴位置
一.文本跟随鼠标并且显示x轴和y轴位置 代码如下: window.onload=function(){ var mydiv = document.createElement("div&quo ...
- 回声状态网络ESN(Echo State Networks)
1.1 网络结构 ESN通过随机地部署大规模系数链接的神经元构成网络隐层,一般称为"储备池".ESN网络具有的特点如下: (1)包含数目相对较多的神经元: (2)神经元之间的连接关 ...
- Android 拖拽功能的使用实例
图片的拖拉功能是处理图片进一个有用且常用的功能,由于手机屏幕尺寸的限制,往往无法在手机上一次性的显示一张比较大的图片,也就是说,我们在手机上一次性只能看到图片的一部分,此时就可以使用图片的拖动功能来拖 ...
- 原生js实现简单的放大镜效果
前言:相信很多同学在浏览购物网站的时候都会用到过放大镜的功能,这个功能在日常的网站也会经常用到.接下来我们开始实现一下它吧: (1)首先了解一下放大镜效果的html架构:如下图,它由两部分组成. ht ...
- Mybatis传多个参数(三种解决方案) mapper.xml的sql语句修改!
第一种 Public User selectUser(String name,String area); 对应的Mapper.xml <select id="selectUser&qu ...
- 《SQL Server 2012 T-SQL基础》读书笔记 - 2.单表查询
Chapter 2 Single-Table Queries GROUP BY之后的阶段的操作对象就是组(可以把一组想象成很多行组成的)了,HAVING负责过滤掉一些组.分组后的COUNT(*)表示每 ...