二分 笔记

news/2024/11/13 11:26:15/文章来源:https://www.cnblogs.com/ad123645/p/18538296

二分

一般来讲我们可能会在以下情况用二分:

  • 求单调函数的零点,或者找个值(二分查找)
  • 求一堆东西的最小值最大(或是最大值最小)是多少(二分答案)
  • 很难直接算出答案,但是很好判定答案合不合法
  • 对于单峰函数,可用二分导函数来代替三分

二分查找

二分是一种可以在\(O(chlogm)\)(m为数据规模,ch为判断状态合法性check()函数时间复杂度)时间复杂度内求解问题的方法,主打一个分治思想,每次将搜索范围减半。

我们以二分查找引入。

有一个有序序列,二分查找的思想如下:

1.定义L,R,mid代表答案在[L,R]内,中点为mid
2.查找mid所在值,如果mid大于查找值,搜索范围定为[L,mid],如果mid小于查找值,搜索范围定为[mid,R],如果查找到了,则返回L。
3.将mid重新设为中点,并调至2。

二分查找的时间复杂度是\(O(logn)\)顺序查找的时间复杂度是\(O(n)\)

代码的话在这:

//二分查找(递归)
//list是待查找的数组,查不到就返回-1代表无解
int binarySearch(int list[],int left,int right,int number)
{if(list==NULL)  return -1;int mid=(right+left)/2;if(left>right)return -1;if(number==list[mid])return mid;//检查中间else if(number>list[mid]) binarySearch(list,mid+1,right,number);//递归搜右边else binarySearch(list,left,mid-1,number);//递归搜左边
}
//二分查找(循环)
int binarySearch(int list[],int left,int right,int number)
{if(list==NULL) return -1;while(left<right){int mid=(right+left)/2;if (list[mid] == number) return mid;//看看中间是不是else if (number > list[mid]) left=mid+1;//搜右边else if (number < list[mid]) right=mid-1;//搜左边}return -1;
}

二分答案

二分答案嘛,就是像二分查找一样,只是判断改了,模板:

while(l<r)
{mid=(l+r)/2;if (check(mid)) r=mid;else l=mid+1;
}

check一般是贪心(写循环、推公式)或DP。

具体应用

比如方程求根啦:

[NOIP2001 提高组] 一元三次方程求解

题目描述

有形如:\(a x^3 + b x^2 + c x + d = 0\) 这样的一个一元三次方程。给出该方程中各项的系数(\(a,b,c,d\) 均为实数),并约定该方程存在三个不同实根(根的范围在 \(-100\)\(100\) 之间),且根与根之差的绝对值 \(\ge 1\)。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后 \(2\) 位。

提示:记方程 \(f(x) = 0\),若存在 \(2\) 个数 \(x_1\)\(x_2\),且 \(x_1 < x_2\)\(f(x_1) \times f(x_2) < 0\),则在 \((x_1, x_2)\) 之间一定有一个根。

输入格式

一行,\(4\) 个实数 \(a, b, c, d\)

输出格式

一行,\(3\) 个实根,从小到大输出,并精确到小数点后 \(2\) 位。

样例 #1

样例输入 #1
1 -5 -4 20
样例输出 #1
-2.00 2.00 5.00

【题目来源】
NOIP 2001 提高组第一题

这提示明摆着疯狂暗示我们二分写check()啊,按提示二分即可:

#include<bits/stdc++.h>
#define db double
using namespace std;
db a,b,c,d,f1,f2;
int cnt=0;
db check(db x){return a*x*x*x+b*x*x+c*x+d;}
int main()
{cin>>a>>b>>c>>d;db l,r,mid;for(db i=-100;i<=100;++i){f1=check(i);f2=check(i+1);if(!f1){printf("%.2lf ",i);cnt++;}if(f1*f2<0){l=i,r=i+1;while(r-l>=0.001){mid=(l+r)/2;if (check(mid)*check(r)>0) r=mid;else l=mid;}printf("%.2lf ",r);cnt++;}if (cnt==3) break;}return 0;
}

小学奥数啦:

小车问题

题目描述

甲、乙两人同时从 A 地出发要尽快同时赶到 B 地。出发时 A 地有一辆小车,可是这辆小车除了驾驶员外只能带一人。已知甲、乙两人的步行速度一样,且小于车的速度。问:怎样利用小车才能使两人尽快同时到达。

输入格式

仅一行,三个实数,分别表示 AB 两地的距离 \(s\),人的步行速度 \(a\),车的速度 \(b\)

输出格式

两人同时到达 B 地需要的最短时间,保留 \(6\) 位小数。

样例 #1

样例输入 #1
120 5 25
样例输出 #1
9.600000
数据规模与约定

对于 \(100\%\) 的数据,保证 \(0 \leq s, a, b \leq 10^9\)

这题不想推公式可以直接二分爽推。

首先,每个人都要坐一次车,而且两个人要同时到达,这样才能使总时间最短。
那么,我们设起点为\(A\),终点为\(B\),小车先带甲开到\(C\)点后,甲下车走到\(B\)点,同时小车掉头与已经走到\(D\)点的乙相向而行,相遇于点\(E\),最后小车带乙向\(B\)开去,和甲同时到达。(拗口拗口阿巴阿巴)
先设\(AC=S\)
那么:
车从\(A\)\(C\)的时间:\(T_{A→C}=\frac{S}{V_{car}}\)
车与乙汇合所用时间:\(T_{B,D→E}=\frac{S-T_{A→C}\times V_{man}}{V_{car}+V_{man}}\)
甲所用时间:\(T_{1}=T_{A→C}+\frac{S_{AB}-S}{Vman}\)
乙所用时间:\(T_{2}=T_{A→C}+ T_{B,D→E}+\frac{S_{AB}-(T_{A→C}+T_{B,D→C})\times V_{man}}{V_{car}}\)

然后二分\(C\)点啦:

#include<bits/stdc++.h>
using namespace std;
int main()
{double s,s1,s2,v1,v2,t1,t2,p;double a,b;scanf("%lf%lf%lf",&s,&v1,&v2);s1=0;s2=s;do{p=(s1+s2)/2.0;a=p/v2;b=(p-a*v1)/(v1+v2);t1=a+(s-p)/v1;t2=a+b+(s-(a+b)*v1)/v2;if(t1<t2)s2=p;else s1=p;}while (fabs(t1-t2)>1e-8);printf("%.6lf",t1);return 0;
}

一堆最小值里求最大值啦:

[NOIP2015 提高组] 跳石头

题目背景

NOIP2015 Day2T1

题目描述

一年一度的“跳石头”比赛又要开始了!

这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 \(N\) 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 \(M\) 块岩石(不能移走起点和终点的岩石)。

输入格式

第一行包含三个整数 \(L,N,M\),分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 \(L \geq 1\)\(N \geq M \geq 0\)

接下来 \(N\) 行,每行一个整数,第 \(i\) 行的整数 \(D_i\,( 0 < D_i < L)\), 表示第 \(i\) 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

输出格式

一个整数,即最短跳跃距离的最大值。

样例 #1

样例输入 #1
25 5 2 
2
11
14
17 
21
样例输出 #1
4

提示

输入输出样例 1 说明

将与起点距离为 \(2\)\(14\) 的两个岩石移走后,最短的跳跃距离为 \(4\)(从与起点距离 \(17\) 的岩石跳到距离 \(21\) 的岩石,或者从距离 \(21\) 的岩石跳到终点)。

数据规模与约定

对于 \(20\%\)的数据,\(0 \le M \le N \le 10\)
对于 \(50\%\) 的数据,\(0 \le M \le N \le 100\)
对于 \(100\%\) 的数据,\(0 \le M \le N \le 50000,1 \le L \le 10^9\)

硬找所有可能的石头方案,让最短跳距尽可能长,一眼\(O(n^{2})\)肯定超时。
那就试试暴力 (其实是小贪心) +二分查找答案\(O(nlogn)\)
跳距离和石头成“反比”,跳距越大,石头越少,跳距越小,石头越多嘛。
直接在[0,L]上二分查找一个跳距\(x\),用贪心看看这个跳距下还能留下多少石头。
\(L\)的大小是\(10^{9}\)之内,求个\(log_{2}(L)\)直接暴降,\(AC\),爽!

#include<bits/stdc++.h>
using namespace std;
int D[50010];
int L,M,N;
bool check(int x)//check用循环写个小贪心
{   int s=0,num=0;D[N+1]=L;for(int i=1;i<=N+1;i++){if(D[i]-s<=x)num++;//记一下某个跳距时,能留下来的石头数量else s=D[i];}if(num>M)return 1;//石头留多了,加税!继续增跳距,减石头else return 0;//石头少了或者刚刚好,地主家都没余粮了,就别减了
}
void solve()
{cin>>L>>N>>M;for(int i=1;i<=N;i++)cin>>D[i];int l=0,r=L;while(l<r){int mid=(l+r)/2;if(check(mid))r=mid;else l=mid+1;}cout<<l;
}
int main()
{int T=1;while(T--) solve();//多测改单测的写法return 0;
}

当然,还有三分啦:

【模板】三分 | 函数

题目描述

给定 \(n\) 个二次函数 \(f_1(x),f_2(x),\dots,f_n(x)\)(均形如 \(ax^2+bx+c\)),设 \(F(x)=\max\{f_1(x),f_2(x),...,f_n(x)\}\),求 \(F(x)\) 在区间 \([0,1000]\) 上的最小值。

输入格式

输入第一行为正整数 \(T\),表示有 \(T\) 组数据。

每组数据第一行一个正整数 \(n\),接着 \(n\) 行,每行 \(3\) 个整数 \(a,b,c\),用来表示每个二次函数的 \(3\) 个系数,注意二次函数有可能退化成一次。

输出格式

每组数据输出一行,表示 \(F(x)\) 的在区间 \([0,1000]\) 上的最小值。答案精确到小数点后四位,四舍五入。

样例 #1

样例输入 #1
2
1
2 0 0
2
2 0 0
2 -4 2
样例输出 #1
0.0000
0.5000

提示

对于 \(50\%\) 的数据,\(n\le 100\)

对于 \(100\%\) 的数据,\(T<10\)\(\ n\le 10^4\)\(0\le a\le 100\)\(|b| \le 5\times 10^3\)\(|c| \le 5\times 10^3\)
三分板子题,二分是三个变量Lmidr分两段,三分就用四个变量LLmidRmidR分三段

#include<bits/stdc++.h>
using namespace std;
vector<double> a(10005),b(10005),c(10005);
int n;
double f(double x)
{double maxx=-0x7fffffff;for(int i=1;i<=n;i++)maxx=max(maxx,a[i]*x*x+b[i]*x+c[i]);return maxx;
}
void solve()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i]>>b[i]>>c[i];double L=0,R=1000;while(L+1e-11<R){double Lmid=L+(R-L)/3;double Rmid=R-(R-L)/3;if(f(Lmid)<=f(Rmid))R=Rmid;else L=Lmid;}cout<<fixed<<setprecision(4)<<f(L)<<endl;
}
int main()
{int T;cin>>T;while(T--)solve();return 0;
}

洛谷二分入门题单:https://www.luogu.com.cn/training/111
牛客二分+三分+01分数规划题单:https://ac.nowcoder.com/acm/contest/22353

再找点洛谷二分题,支持边学边练(参考大佬call_of_silence的题单)
P1102:easy。
P1676:贪一手。
P1083:前缀和优化check,不会前缀和别写。 (不过能看到这里的应该都学会差分前缀和了吧)
P1314:直接模拟,二分出参数\(W\),再把\(W\)带入求得\(|s-y|_{minn}\)check()里前缀和优化,时间复杂度\(O(nlogn)\)
P1678:排个序,二分查找,比较刚好比自己大一点的那个大学与刚好比自己小一点的大学做差比较绝对值,累加。
P1824:先排序,二分最近距离。一旦距离大于check()x,那么牛的数量++,最后比较牛的总数与当前距离满足要求可以住下的牛的总数。
P2249:二分查找,lower_bound()upper_bound()的应用。
P1163:小数(实数)二分板子题,二分每个月的月利息,然后纯模拟。
P2390:和例题那个石头思路有点想,不过这题其实使用贪心,可能还好想一点。
P2920:原数组按结束时间升序排序,然后二分最早开始的时间,不过贪心做更爽。
P4058:二分时间,注意木料必须是一整棵树 (卡我好久)
P1182&P2855&P3853:三道和例题跳石头的类题摆一起,三倍经验,二分最小的最大距离,每一次check()扫一遍,距离大于check(x)x,就记录一下,最后判断按照这个距离需要分几段,与题目要求进行比较。(其中第一道和原题差不多,后两道变了一点)
P2440&P1577:类题,双倍经验,只不过一道是整数,一道是实数二分,二分长度len
P1570:小贪心,每一次check需要排序+贪心,贪一手,时间复杂度\(O(nlogn)\)(差不多,还有一部分复杂度不想算了)
P1873:二分高度,时间复杂度\(O(nlogn)\)
P1843:模拟,二分最少用的天数,在一定天数内由自然晒干的continue,对于每一个干不了的使用机器(注意机器只能以整数天使用,你每天可以烘干5点的机器去干一件一点的衣服也需要一天),所以除的时候向上取整,最后判断天数是否可以接受。
P1661:二分+并查集混题,可以速学一下并查集板子来做这题。
P3743:小数二分,类似P1843一样处理,电用完了就找充电宝,这里的充电宝支持小数时间的充电。
P2985:二分最不开心的一天的开心值,模拟,输出时如果还有糖果没有吃完那么默认没吃完的糖果留在最后一天吃。
P8666:多维差分板子题,也可以用二分(麻烦,其实可以用这题把多维差分复习一下,没学的直接学了再写)。
P1281:计算总页数,二分答案(思路类似前面的三倍经验)——计算出最多的人需要的最短的时间,然后以这个最短的时间为标准再扫一遍,处理出每一个人需要的做的页数,排序,保证最前面的人做的活最少。
P3611:二分答案,check()模拟的时候可能需要用到优先队列priority_queue<int,vector<int>,greater<int>>(又叫大根堆),简称pqpq也是赛时贪心常客了,可以先混个脸熟。
P1542:直接模拟,小数二分,注意快递员是只能在\(l_{1}\)\(r_{1}\)之间送货。
P4447:贪心+二分查找。
P3957:难得找到个check()里面是DP的典题。
P1663:要二分找到最小的,使阴影区间存在的\(y\)值,关键在写check()藏了道初中数学题 ,计算出\(n-1\)条斜线的解析式,然后小数二分,二分最低的\(y\)值,对于每一个解析式,带入\(y\)解出不等式,根据\(a[i]\)的正负可以得出解得区间“方向”,进而确定需要记录的区间边界\(l\)\(r\),用两个全局变量数组\(l[i]\)\(r[i]\)记录,然后找到最大左边界和最小右边界,最后判断是否有解,有解则说明当前的\(y\)值是可以接受的。最后输出就可以了。
P3933:给一个矩阵,你能把它分成两个部分,分割线需要是阶梯状,求使得两个部分极差最大值的最小值(是不是又见到这个东西了?一堆东西“最小值最大”或“最大值最小”果断二分)。四个方向每个方向都要一次二分答案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/830735.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现二

该系统总共24张表,代码整洁,每个功能、接口上都有注释说明。 运行环境:jdk1.8、mysql5.x、eclipse/idea、maven3.5/3.6 包远程运行的哦。 特色功能:发布课程、学习课程、分享资料、资料讨论等。 部分功能:课程收藏信息实体类Entity、课程订单信息实体类Entity、课程评论信…

Forgejo 安全漏洞(CVE-2023-49948) 复现

影响: 攻击者通过在URL中添加.rss(或其他扩展名)来测试私有用户账户的存在。攻击者可以利用该漏洞获取敏感信息,增加隐私风险 将个人账号设置为私有` https://codeberg.org/forgejo/forgejo/commit/d7408d8b0b04afd2a3c8e23cc908e7bd3849f34d routers/web/user/home.go @ -…

SRE云计算运维之基础篇二:权限管理,VIM工具,文件查询及shell基础

目录文件权限管理 访问控制列表ACL VIM的使用及内容查询 文本三剑客 基本正则和扩展正则 shell脚本之变量简单总结一下linux中的权限 1.首先介绍一下关于linux中的用户: Linux中每个用户是通过 User Id (UID)来唯一标识的,且Linux中可以将一个或多个用户加入用户组中,用户…

ARM架构

CPU内部结构CPU的核心为ALU(8位的单片机,指定的是ALU里面处理的数据为8位)32位单片机内部ALU(一次性可以计算两个32位数据)8位单片机代表的是ALU能够一次处理的数据是8位的,也是代表传输数据的数据总线是8位的(32位同理)地址空间RISC与CISC RISC指令CISC指令CPU内部寄存器CPU内…

《计算机基础与程序设计》第7周学习总结

学期(2024-2025-1) 学号(20241428) 《计算机基础与程序设计》第7周学习总结 作业信息 |这个作业属于哪个课程|<班级的链接>(如[2024-2025-1-计算机基础与程序设计](https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP|)| |-- |-- | |这个作业要求在哪里|<作…

基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现一

技术点:SpringBoot+SpringDataJPA+Mysql+Freemaker+Bootstrap+JS+CSS+HTML 特色功能:发布课程、学习课程、分享资料、资料讨论等。 部分功能:前台用户信息实体类Entity、新闻信息实体类Entity、课程分类信息实体类Entity、课程信息实体类Entity、角色信息实体类Entity、用户…

『模拟赛』NOIP2024(欢乐)加赛3

『模拟赛记录』NOIP2024(欢乐)加赛3Rank 真欢乐吗, 不过 mission accomplished.A. Sakurako and Water CF2033B *900 byd 还懂难易搭配,不过这个 b 翻译甚至不着重以下主对角线差评,被硬控半个小时,直到手模样例才发觉不对。 读懂题就很简单了,最优一定是找最长的对角线…

权限系统:一文搞懂功能权限、数据权限

大家好,我是汤师爷~ 在权限系统中,权限通常分为两大类:功能权限和数据权限。这两种权限相辅相成,共同决定了用户在系统中可以执行哪些操作、访问哪些信息。 功能权限 1、功能权限是什么 当登录某个系统时,为什么有些功能按钮是灰色的,而有些页面甚至完全不可见?这正是功…

2024.10.30(Maven)

Main放源代码 test放测试代码 pom.xml项目核心配置文件 Maven的主要功能有: 1.提供了一套标准化的项目结构 2.听了一套标准化的构建流程(编译、测试、打包、发布....) 3.提供了一套依赖管理机制

【日记】你们两个熊孩子,不要叫我叔叔啊啊啊啊(1630 字)

正文今天上午起床,窗外地面湿了。瞬间不想出门吃饭了。挣扎了一会儿,还是带着伞出门了。毕竟昨天说了要出门剪头发。花了一个小时吧好像。指定的那个理发店还挺远。理发师都认识我了,笑了笑,问我怎么剪。我还是说只修一下刘海,不要遮住眉毛和眼睛就行,后面和侧边还要继续…

东商项目mysql实例库(dingding)增量备份的实现

一、钉钉库(dingding)实例全量备份 1.机器:cvlink-xxcc-prd1172.16.50.59cvlink-xxcc-prd2172.16.50.60备注:59是主库,60为从库,因为做了主从,所以两个数据库数据是一致的,直接对从库60的实例钉钉进行备份即可。2.对从库60的实例进行备份: 2.1 登录从库:2.2 进行备份…

安娜的档案(Anna’s Archive)官网最新镜像网站入口(实时更新)

安娜的档案(Anna’s Archive)是一个广受欢迎的在线资源平台,汇集了Z-Library、Library Genesis和Sci-Hub等资源,拥有超过2000万册书籍和9000万篇论文。该网站提供多种下载选项,包括快速、慢速、libgen、IPFS和Tor浏览器下载,以满足不同用户的网络和需求。用户可以无需注册…