news 2026/6/23 18:22:20

刷题日记day5(二分+前缀和)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
刷题日记day5(二分+前缀和)

题目描述

蒟蒻的第五篇博客希望大家支持

  • 1314聪明的质检员

P1314 [NOIP 2011 提高组] 聪明的质监员

题目描述

小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n nn个矿石,从1 11n nn逐一编号,每个矿石都有自己的重量w i w_iwi以及价值v i v_ivi。检验矿产的流程是:

  1. 给定m mm个区间[ l i , r i ] [l_i,r_i][li,ri]
  2. 选出一个参数W WW
  3. 对于一个区间[ l i , r i ] [l_i,r_i][li,ri],计算矿石在这个区间上的检验值y i y_iyi

y i = ∑ j = l i r i [ w j ≥ W ] × ∑ j = l i r i [ w j ≥ W ] v j y_i=\sum\limits_{j=l_i}^{r_i}[w_j \ge W] \times \sum\limits_{j=l_i}^{r_i}[w_j \ge W]v_jyi=j=liri[wjW]×j=liri[wjW]vj

其中j jj为矿石编号,[ p ] [p][p]是指示函数,若条件p pp为真返回1 11,否则返回0 00

这批矿产的检验结果y yy为各个区间的检验值之和。即:∑ i = 1 m y i \sum\limits_{i=1}^m y_ii=1myi

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

输入格式

第一行包含三个整数n , m , s n,m,sn,m,s,分别表示矿石的个数、区间的个数和标准值。

接下来的n nn行,每行两个整数,中间用空格隔开,第i + 1 i+1i+1行表示i ii号矿石的重量w i w_iwi和价值v i v_ivi

接下来的m mm行,表示区间,每行两个整数,中间用空格隔开,第i + n + 1 i+n+1i+n+1行表示区间[ l i , r i ] [l_i,r_i][li,ri]的两个端点l i l_ilir i r_iri。注意:不同区间可能重合或相互重叠。

输出格式

一个整数,表示所求的最小值。

输入输出样例 #1

输入 #1

5 3 15 1 5 2 5 3 5 4 5 5 5 1 5 2 4 3 3

输出 #1

10

说明/提示

【输入输出样例说明】

W WW4 44的时候,三个区间上检验值分别为20 , 5 , 0 20,5,020,5,0,这批矿产的检验结果为25 2525,此时与标准值S SS相差最小为10 1010

【数据范围】

对于10 % 10\%10%的数据,有1 ≤ n , m ≤ 10 1 ≤n,m≤101n,m10

对于30 % 30\%30%的数据,有1 ≤ n , m ≤ 500 1 ≤n,m≤5001n,m500

对于50 % 50\%50%的数据,有1 ≤ n , m ≤ 5 , 000 1 ≤n,m≤5,0001n,m5,000

对于70 % 70\%70%的数据,有1 ≤ n , m ≤ 10 , 000 1 ≤n,m≤10,0001n,m10,000

对于100 % 100\%100%的数据,有1 ≤ n , m ≤ 200 , 000 1 ≤n,m≤200,0001n,m200,0000 < w i , v i ≤ 1 0 6 0 < w_i,v_i≤10^60<wi,vi1060 < s ≤ 1 0 12 0 < s≤10^{12}0<s10121 ≤ l i ≤ r i ≤ n 1 ≤l_i ≤r_i ≤n1lirin

思路分析

注意到题目让我们最小化某一个值,这种题目往往采用二分答案的方法,有些时候我们是直接二分答案的范围,有些时候我们是二分一个中间变量的范围,再得到答案,此题为后者。我们再分析一下题目是否有某种单调性,假设起始状态给了一个无限大的基准值W,那么y就等于0,那么s-y==s,随着基准值W的减小,会让公式所求值y变小,接着目标值s-y就会变小,显然有单调性,我们确定了方法二分答案。
接着是如何具体处理这个问题,我们会发现,随着y的不断减小,目标值s-y有可能是负数,这也就是我们二分判断边界的关键逻辑,当s-y大于等于0时,我们要让y增大,即W减小,即r=mid,当s-y小于0时,我们要让y减小,即W增大,即l=mid

代码展示

#include<iostream>#include<algorithm>#include<cstring>#include<vector>#definexfirst#defineysecondusingnamespacestd;typedeflonglongLL;typedefpair<LL,LL>PLL;constintN=2*1e5+10;LL n,m,s;LL w[N],val[N],temp[N],sum_temp[N];intcnt[N],sum_cnt[N];vector<PLL>q;LLcheck(LL x){memset(cnt,0,sizeofcnt);memset(sum_cnt,0,sizeofsum_cnt);memset(sum_temp,0,sizeofsum_temp);memcpy(temp,val,sizeofval);LL ans=0;for(inti=1;i<=n;i++){if(w[i]>=x)cnt[i]++;elsetemp[i]=0;}for(inti=1;i<=n;i++)sum_cnt[i]=sum_cnt[i-1]+cnt[i];for(inti=1;i<=n;i++)sum_temp[i]=sum_temp[i-1]+temp[i];for(inti=0;i<q.size();i++){LL l=q[i].x,r=q[i].y;ans+=(LL)(sum_cnt[r]-sum_cnt[l-1])*(sum_temp[r]-sum_temp[l-1]);}returns-ans;}intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m>>s;for(inti=1;i<=n;i++){LL x,y;cin>>x>>y;w[i]=x,val[i]=y;}while(m--){LL x,y;cin>>x>>y;q.push_back({x,y});}LL l=0,r=1e6+1;while((l+1)!=r){LL mid=(l+r)/2;if(check(mid)>=0)r=mid;elsel=mid;//cout<<l<<" "<<r<<endl;}//cout<<abs(check(l))<<endl;//cout<<abs(check(r))<<endl;cout<<min(abs(check(l)),abs(check(r)))<<endl;return0;}

细节问题

每次调用check函数都是需要初始化的,仔细读题正确翻译那个公式的意思
为什么题号是1314这让单身狗心很痛好嘛,做题还被伤害了

AI详细注释代码

#include<iostream>#include<algorithm>#include<cstring>#include<vector>#definexfirst// pair的第一个元素(区间左端点)#defineysecond// pair的第二个元素(区间右端点)usingnamespacestd;typedeflonglongLL;// 用LL避免数据溢出(结果可能很大)typedefpair<LL,LL>PLL;// 存储区间的左右端点(l,r)constintN=2*1e5+10;// 数组最大长度(适配n,m<=2e5)// 全局变量LL n,m,s;// n=矿石数,m=区间数,s=标准值LL w[N],val[N];// w[i]=第i个矿石重量,val[i]=第i个矿石价值LL temp[N],sum_temp[N];// temp[i]=筛选后的矿石价值,sum_temp=temp的前缀和intcnt[N],sum_cnt[N];// cnt[i]=标记矿石是否≥W,sum_cnt=cnt的前缀和vector<PLL>q;// 存储所有区间[l,r]// 检查函数:给定参数W=x,计算检验值与标准值s的差值(s - 总检验值)LLcheck(LL x){// 初始化前缀和/标记数组为0memset(cnt,0,sizeofcnt);memset(sum_cnt,0,sizeofsum_cnt);memset(sum_temp,0,sizeofsum_temp);// 拷贝原始价值数组到temp(后续仅修改不满足条件的位置)memcpy(temp,val,sizeofval);LL ans=0;// 存储总检验值// 1. 标记满足w[i]≥x的矿石,并清空不满足的矿石价值for(inti=1;i<=n;i++){if(w[i]>=x)cnt[i]++;// 满足条件,标记为1elsetemp[i]=0;// 不满足条件,价值置0}// 2. 计算前缀和(快速求区间内满足条件的矿石数/价值和)for(inti=1;i<=n;i++)sum_cnt[i]=sum_cnt[i-1]+cnt[i];// 前缀和:1~i中≥x的矿石数量for(inti=1;i<=n;i++)sum_temp[i]=sum_temp[i-1]+temp[i];// 前缀和:1~i中≥x的矿石价值和// 3. 遍历所有区间,计算总检验值for(inti=0;i<q.size();i++){LL l=q[i].x,r=q[i].y;// 当前区间的左右端点// 区间内满足条件的矿石数 × 区间内满足条件的矿石价值和 → 累加总检验值ans+=(LL)(sum_cnt[r]-sum_cnt[l-1])*(sum_temp[r]-sum_temp[l-1]);}returns-ans;// 返回标准值与总检验值的差值(用于二分判断)}intmain(){// 加速cin/cout,避免大数据量超时ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);// 输入基础参数:矿石数、区间数、标准值cin>>n>>m>>s;// 输入每个矿石的重量和价值for(inti=1;i<=n;i++){LL x,y;cin>>x>>y;w[i]=x,val[i]=y;}// 输入所有区间,存入vectorwhile(m--){LL x,y;cin>>x>>y;q.push_back({x,y});}// 二分查找最优W值:W范围0~1e6+1(w[i]≤1e6)LL l=0,r=1e6+1;while((l+1)!=r){// 二分终止条件:左右边界相邻LL mid=(l+r)/2;// 中间值if(check(mid)>=0)r=mid;// 差值≥0 → 需增大W,缩小右边界elsel=mid;// 差值<0 → 需减小W,扩大左边界}// 比较最终两个边界的差值绝对值,取最小值(最优解)cout<<min(abs(check(l)),abs(check(r)))<<endl;return0;}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/22 21:17:09

005-AES:采招网

本文来做一个标准AES案例&#xff1a;采招网 找加密参数 这里有一个响应是密文&#xff0c;今天来解密响应内容&#xff1a; 找解密位置 试过hook&#xff0c;直接pass掉&#xff0c;因为鼠标一移动到页面上就会断下来&#xff0c;可以试试再加些条件来判断&#xff08;类似条…

作者头像 李华
网站建设 2026/6/23 3:32:39

基于python+django的在线考试系统(源码+lw+部署文档+讲解等)

课题介绍本课题聚焦传统线下考试组织繁琐、阅卷效率低、成绩统计不便的痛点&#xff0c;设计并开发基于PythonDjango的在线考试系统。系统以Python作为核心开发语言&#xff0c;依托Django框架搭建高效稳定的后端服务架构&#xff0c;负责处理多角色权限管控、题库管理、试卷生…

作者头像 李华
网站建设 2026/6/22 6:39:17

C语言一维与二维数组名详解:从本质理解到高手应用

在C语言中&#xff0c;数组名看似简单&#xff0c;却是许多初学者容易混淆的重点和难点。理解数组名的本质&#xff0c;是掌握C语言数组编程的关键一步。数组是C语言中最基础且重要的数据结构之一&#xff0c;而数组名作为数组的标识符&#xff0c;其背后隐藏的语义和特性对于初…

作者头像 李华
网站建设 2026/6/23 17:59:36

当水印遇见AI:一场像素级的美学修复之旅

当水印遇见AI&#xff1a;一场像素级的美学修复之旅 【免费下载链接】IOPaint 项目地址: https://gitcode.com/GitHub_Trending/io/IOPaint 那张珍藏多年的老照片&#xff0c;右下角却印着碍眼的网站标识&#xff1b;精心收藏的漫画插图&#xff0c;被版权水印破坏了整…

作者头像 李华
网站建设 2026/6/23 5:19:33

软件测试是保障软件质量的关键环节,尤其在当前无法完全依赖形式化方法证明软件正确性的背景下,测试成为发现缺陷最主要、最有效的手段

一、前文铺垫中的任务管理部件与数据管理部件&#xff0c;构成了软件系统运行的基础支撑环境。任务管理部件通过识别事件驱动、时钟驱动及优先级相关的任务&#xff0c;确保系统行为的有序性和实时性&#xff1b;而数据管理部件则屏蔽底层存储差异&#xff0c;提供统一的数据访…

作者头像 李华
网站建设 2026/6/22 22:56:59

如何用AI快速生成Flink面试题答案?

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个AI辅助工具&#xff0c;能够根据用户输入的Flink面试题自动生成详细的解答。解答应包括&#xff1a;1. 问题分析&#xff1b;2. 核心概念解释&#xff1b;3. 代码示例&…

作者头像 李华