1 月 29日算法练习-二分法

news2024/10/6 10:31:49

二分法是一种高效的查找方法,它通过将问题的搜索范围一分为二(两边具有明显的区别),迭代地缩小搜索范围,直到找到目标或确定目标不存在。
二分法适用于有序数据集合,并且每次迭代可以将搜索范围缩小一半。
二分法本质上也是枚举,但和暴力枚举不同,二分法利用数据结构的单调性减少了很多不必要的枚举,从而极大地提高了效率,一般可以将O(n)的枚举优化到O(logn)。
常见的二分类型有:
1)整数二分
2)浮点二分
3)二分答案(最常见)

1.研究并发现数据结构(或答案变量)的单调性。
2.确定最大区间1,,确保分界点一定在里面,具体有一些细节:若以r作为答案,那么答案区间在[1+1,r],若以1作为答案,那么答案区间在[1,r-1]。
3.确定check函数,一般为传入mid(区间中某个下标),返回mid所属区域或返回一个值,当check函数较简单时可以直接判断。
参数
4.计算中点mid=(1+r)/2,用check判断该移动l或r指针,具体移动哪个需要根据单调炒以及要求的答案来判断。
5.返回1或r,根据题意判断。

整数二分就是在一个已有的有序数组上,进行二分查找,一般为找出某个值的位置或者是找出分界点。
这个数组肯定是开的下的,其数组大小一般在1e6以内。区域划分如左图。
在这里插入图片描述

二分答案是二分法中最常见也最重要的题型,考察的比较灵活,需要选手从题目中发现某个单调的函数,然后对其进行二分。
常见的模型是:
二分框架(时间复杂度O(logm)+ check函数(时间复杂度O(n)
一般情况下,我们会将答案进行二分,然后在枚举出某个可能解后判断其是否可以更优或者是否合法,从而不断逼近最优解。
二分答案的题的特征:如果已知某个答案,很容易判断其是否合法或更优。某些贪心问题可能可以转化成二分答案问题。

123

思路:用前缀和枚举,复杂度高,只能过 40%。这题需要利用数学解来降低复杂度。找到数学规律,利用二分求出第 l,和 r 位的组数,再求出位数,有了组数和位数就能通过数学规律或前缀和求出 l 和 r 位的值。在这里插入图片描述

样例输入
3
1 1
1 3
5 8
样例输出
1
4
8

请添加图片描述

#include<iostream>
using namespace std;
using ll = long long;
//const int N = 2e6+10;
//int pre[N];
int T;


ll getPre(ll i){
    return i*(i+1)*(i+2)/6;
}

ll cula(ll x){
    ll i = 0,l = 0,r = 2e6;
    while(l<=r){
        ll mid = (l+r)>>1;
        if(mid*(mid+1)/2 > x)r = mid - 1,i = mid;
        else l = mid + 1;
    }
    ll j = x - (i-1)*(i-1+1)/2;
    
    return getPre(i-1) + j*(j+1)/2;
//    return pre[i-1]+j*(j+1)/2;
}

int main( ){
//    pre[1] =1;
//    for(int i=1;i<=2000000;i++)pre[i] = pre[i-1] + i*(i+1)/2;

    cin>>T;
    while(T--){
        ll l,r;cin>>l>>r;
        cout<<cula(r)-cula(l-1)<<'\n';
    }
    return 0;
}

跳石头

  • 思路:发现当“最短跳跃距离”越长时,需要移走的石头数量也越多。于是就产生了单调性,我们通过二分“最短跳跃距离”,在已知“最短跳跃距离”的情况下容易O(n)计算需要搬走的石头的数量,找到分界点即可(即在至多搬走M块石头的情况下的最远跳跃距离)。
    在这里插入图片描述
#include<iostream>
using namespace std;
const int N = 1e5;
using ll = long long;
ll l,n,m;
int a[N];

ll check(ll mid){
    int res = 0,last = 0;
    for(int i=1;i<=n;i++){
        if(a[i]-a[last]<mid){
            res++;
            continue;
        }
        last = i;
    }
    if(l-a[last]<mid)return m+1;
    return res;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>l>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    
    ll left = 0,r = 1e9+9;
    while(left+1!=r){
        ll mid = (left+r)/2;
        
        if(check(mid)<=m)left=mid;
        else r=mid;
    }
    cout<<left<<'\n';
    return 0;
}

肖恩的苹果林

这题和上一题特征明显,要求的是“最大的最近距离”,当通过二分枚举出一个最近距离时,我们可以判断其合法性(即贪心地判断是否能够放得不m棵树苗),如果合法说明这个距离也许可以再变大,如果不合法就说明这个最近距离应该变小。
在这里“最近距离mid”和“种树的数量check(m是负相关的关系。

在这里插入图片描述

#include<iostream>
using namespace std;
const int N = 1e5+10;
using ll = long long ;
int n,m,a[N];
ll check(ll mid){
    int res=0;
    for(int i=1,lst=0;i<=n;i++){
        if(lst&&a[i]-a[lst]<mid)continue;
        res++,lst=i;
    }
    return res;
}

int main( ){
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    
    ll l = 0,r=1e9+10;
    while(l+1!=r){
        ll mid = (l+r)>>1;
        if(check(mid)>=m)l=mid;
        else r=mid;
    }
    cout<<l<<'\n';
    return 0;
}

肖恩的乘法表

思路:因为 k 和元素个数呈现单调性,所以可以利用二分枚举答案元素,通过用数学规律来计算出每行<k 的数得到全部<k 的数来判断是否答案满足,从而利用二分夹逼得到最终答案,注意边界r 是满足条件的最小值。

通过排名去计算元素是不好算的,但是如果已知一个元素可以利用矩阵每一行的规律来O(n)地计算排名。
所以我们枚举元素大小,设rnk(x)表示矩阵中小于等于x的元素的个数,那么对于第i行<=x的数字的个数就是min(m,x/ i)。
必然有rnk(l)<k,rnk(r)>=k,从而将整个整数域划分部分,最后返回r即可。

在这里插入图片描述

#include<iostream>
using namespace std;
using ll = long long;
ll n,m,k;

ll check(ll mid){
    int res=0;
    for(int i=1;i<=n;i++){
        res+=min(m,mid/i);
    }
    return res;
}

int main( ){
    cin>>n>>m>>k;
    ll l = 0,r = 1e12;
    while(l+1!=r){
        ll mid = (l+r)>>1;
        if(check(mid)>=k)r=mid;
        else l=mid;
    }
    cout<<r<<'\n';
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STL_list

一、有关list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。Ii…

备战蓝桥杯--数据结构及STL应用(基础)

今天轻松一点&#xff0c;讲一讲stl的基本操作吧&#xff01; 首先&#xff0c;让我们一起创建一个vector容器吧&#xff01; #include<bits/stdc.h> using namespace std; struct cocoack{ int coco,ck; } void solve(){vector<cocoack> x;for(int i0;i<5;i){…

负载均衡技术助力企业数字化转型和高可用架构实现

文章目录 什么是高可用架构什么是负载均衡负载均衡设备硬件负载均衡的代表产品软件负载均衡的代表产品 负载均衡基于OSI模型分层负载均衡在网络层负载均衡在传输层负载均衡在应用层 优先考虑负载均衡的场景硬件负载均衡的缺点云负载均衡正在成为最佳选择企业数字化转型对负载均…

Ubuntu 22.04 中文乱码解决方案

sudo apkg-reconfigure locales 按空格键选中

数字图像处理(实践篇)三十六 OpenCV-Python 使用ORB和BFmatcher对两个输入图像的关键点进行匹配实践

目录 一 涉及的函数 二 实践 ORB(Oriented FAST and Rotated BRIEF)是一种特征点检测和描述算法,它结合了FAST关键点检测和BRIEF描述子。ORB算法具有以下优势: ①实时性:能够在实时应用中进行快速的特征点检测和描述。 ②

跟着cherno手搓游戏引擎【14】封装opengl

本节先把代码粘上&#xff0c;后续会慢慢把注释都给加上&#xff0c;先看代码了解个大概&#xff08;待更新&#xff09; 前置&#xff1a; RendererAPI.h: #pragma once namespace YOTO {enum class RendererAPI {None 0,OpenGL1};class Renderer {public:inline static R…

交换排序(快排)

当当当当&#xff01;终于来到了令人激动人心的环节&#xff1a;交换排序&#xff01;在这里&#xff0c;我们将会学习到一个大家经常听到过的名词&#xff1a;快速排序&#xff0c;而我希望通过这篇文章的学习&#xff0c;大家也能够真正的学会快排&#xff01; 交换排序 基本…

SkyWalking+es部署与使用

第一步下载skywalking :http://skywalking.apache.org/downloads/ 第二步下载es:https://www.elastic.co/cn/downloads/elasticsearch 注&#xff1a;skywalking 和es要版本对应&#xff0c;可从下面连接查看版本对应关系&#xff0c;8.5.0为skywalking 版本号 Index of /di…

Scala入门01

Spark入门 1.入门 spark采用Scala语言开发 Spark是用来计算的 Scala掌握&#xff1a;特性&#xff0c;基本操作&#xff0c;集合操作&#xff0c;函数&#xff0c;模式匹配&#xff0c;trait&#xff0c;样例类&#xff0c;actor等内容。 2.内容讲解 2.1 Scala简介 在http…

idea报错(建一个数据库和里面的表)

//报错1 2024-01-30 11:36:50.652 ERROR 21136 --- [nio-9090-exec-5] c.e.exception.GlobalExceptionHandler : 异常信息&#xff1a; 前端没有传数据就会报这个错 //报错2 Caused by: java.sql.SQLException: Access denied for user rootlocalhost (using password: YES…

【UEFI实战】Redfish的BIOS实现——生成EDK数据

生成Redfish文件 Redfish数据的表示形式&#xff0c;最常用的是JSON。将JSON表示的数据转换成C语言可以操作的结构体&#xff0c;是必不可少的步骤。当然如果手动转换的话&#xff0c;需要浪费大量的时间&#xff0c;因此DMTF组织开发了一个工具&#xff0c;用于将JSON数据快速…

redis-4 集群

应用场景 为什么需要redis集群&#xff1f; 当主备复制场景&#xff0c;无法满足主机的单点故障时&#xff0c;需要引入集群配置。 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服…

论文笔记:多任务学习模型:渐进式分层提取(PLE)含pytorch实现

整理了RecSys2020 Progressive Layered Extraction : A Novel Multi-Task Learning Model for Personalized Recommendations&#xff09;论文的阅读笔记 背景模型代码 论文地址&#xff1a;PLE 背景 多任务学习&#xff08;multi-task learning&#xff0c;MTL&#xff09;&a…

【C/C++ 01】初级排序算法

排序算法通常是针对数组或链表进行排序&#xff0c;在C语言中&#xff0c;需要手写排序算法完成对数据的排序&#xff0c;排序规则通常为升序或降序&#xff08;本文默认为升序&#xff09;&#xff0c;在C中&#xff0c;<algorithm>头文件中已经封装了基于快排算法的 st…

Leetcode3015. 按距离统计房屋对数目 I

Every day a Leetcode 题目来源&#xff1a;3015. 按距离统计房屋对数目 I 解法1&#xff1a;暴力 暴力枚举每一个房屋对 (i, j) 的 3 种路径&#xff1a; i->j&#xff1a;长度为 len1 j-i&#xff1b;i->x->y->j&#xff1a;长度为 len2 abs(i - x) 1 a…

解决Linux环境下gdal报错:ERROR 4: `/xxx.hdf‘ not recognized as a supported file format.

网上查了一堆资料&#xff0c;五花八门&#xff0c;总结了一下可能的原因&#xff1a; ① gdal不支持该格式 使用命令“gdalinfo --formats” 即可查看当前环境中的gdal所能支持的数据格式。如下图&#xff08;没截完整&#xff0c;下面还有一大串&#xff09;。 这个是很常见…

Java代码混淆加密之ClassFinal

一:介绍 ClassFinal是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;可避免源码泄漏或字节码被反编译。 二:功能特性 无需修改原项目代码,只要把编译好的jar/war包用本工具加密即可。运行加密项目时,无需求修…

iText操作pdf

最近有个任务是动态的创建pdf根据获取到的内容&#xff0c;百度到的知识点都比较零散&#xff0c;官方文档想必大家也不容易看懂。下文是我做出的汇总 public class CreatePdfUtils {public static void create(){//准备File file new File("C:\\code\\base-project-back…

STM32矩形(矩阵)按键(键盘)输入控制LED灯 ——4*4矩阵按键源码解析

本文基于标准函数库的工程实现stm32F103C8T6使用4*4的矩阵按键控制LED灯的亮灭及闪烁等功能。 程序源码&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1_MPhvMduKCTP0MPG-Gtw3A?pwd2syk 提取码&#xff1a;2syk 文章目录 一、矩形键盘介绍 1、硬件电路基本原理 …

Sketch 英文转中文:轻松搞定

Sketch版本的转换一直是每个人的关键问题。现在UI设计领域有很多UI设计软件&#xff0c;但大部分都是英文版。对于国内英语基础差的设计师来说&#xff0c;使用这样的软件无形中增加了工作量&#xff0c;往往需要在设计编辑的同时查阅翻译。中文Sketch版本替代即时设计详细介绍…