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

有关算法:

二分答案;

但是你只二分答案是不够的,因为你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. MSSQL时间格式转换

    sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: ), 时间一, ) 结果: :/*时间一般为getdate()函数或数据表里的 ...

  2. linux下安装MySQL(mariadb)

    MySQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可. 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源 ...

  3. Centos logrotate截断tomcat日志文件

    1. 设置logrotate轮转日志文件 tomcat日志目录:/usr/local/tomcat/apache-tomcat-8.5.34/logs /etc/logrotate.d/目录下创建to ...

  4. js+php大文件分片上传

    1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...

  5. Improving Network Management with Software Defined Networking

    Name of article:Improving Network Management with  Software Defined Networking Origin of the article ...

  6. ps 等程序的选项的三种风格

    unix options bsd options gnu long options unix options, which may be grouped and must be preceded by ...

  7. 设计模式-Runoob:设计模式简介

    ylbtech-设计模式-Runoob:设计模式简介 1.返回顶部 1. 设计模式简介 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用.设计模式是 ...

  8. DRF中的视图集的使用

    1.说明:DRF框架中的视图集: 在drf开发接口中,使用GenericAPIView和视图扩展类结合起来完成接口功能是一件很常见的事情,所以,drf的作者帮我们提前把  GenericAPIView ...

  9. java.lang.NoClassDefFoundError: org/bouncycastle/jce/provider/BouncyCastleProvider解决方法

    因为加入了jdk的第三方安全库,需要额外配置 1.下载bcprov-jdkxx-xxx.jar 2.将bcprov-jdkxx-xxx.jar放入$JAVA_HOME/jre/lib/ext下 3.打 ...

  10. npm构建vue项目

    环境搭建 我们需要先从node.js官网安装node,安装过程很简单,一路“下一步”就可以了(傻瓜式安装). 安装完成之后,打开命令行工具(Mac打开终端),输入 node -v,如图,如果出现相应的 ...