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

二分法是一种高效的查找方法,它通过将问题的搜索范围一分为二(两边具有明显的区别),迭代地缩小搜索范围,直到找到目标或确定目标不存在。
二分法适用于有序数据集合,并且每次迭代可以将搜索范围缩小一半。
二分法本质上也是枚举,但和暴力枚举不同,二分法利用数据结构的单调性减少了很多不必要的枚举,从而极大地提高了效率,一般可以将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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【GAMES101】Lecture 12 阴影 Shadow Mapping

这里是光栅化的最后一部分&#xff0c;讲这个光栅化里面怎么实现这个阴影 实际上阴影就是光源看不到的地方但是是我们能看到的地方&#xff0c;那这个地方就应该有阴影&#xff0c;那具体怎么做呢&#xff0c;这个就叫做Shadow Mapping&#xff0c;分两步做 我们之前说过这个解…

初识attention

近年来&#xff0c;attention机制在机器视觉和机器翻译领域受到了广泛的关注&#xff0c;有很多文章都是融合attention来提高性能。attention受启发于人类的视觉系统&#xff0c;最先应用于序列化的机器翻译(NLP)后又推广到计算机视觉中&#xff0c;本篇文章就来简单学习一下at…

[GN] 设计模式——面向对象设计原则概述

文章目录 面向对象设计原则概述单一职责原则开闭原则里氏代换原则依赖倒转原则接口隔离原则合成复用原则迪米特法则 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 面向对象设计原则概述 单一职责原则 一个类只负责一个功能领域中的相应职责 类…

JavaScript DOM属性和方法之attribute属性对象

在HTML的DOM中&#xff0c;attribute对象表示HTML属性。HTML属性始终属于HTML元素&#xff0c;它在DOM节点中被称为属性节点。在DOM中&#xff0c;NamedNodeMap对象表示元素属性节点的无序集合&#xff0c;我们可以通过指定的索引访问指定的属性。通过element对象的attribute属…

【Leetcode】两数之和

目录 题目&#xff1a; 解法1&#xff1a;暴力双for 1.想到的第一种方法两for循环解 复杂度分析 解法2&#xff1a;hash表 总结&#xff1a; 笔记&#xff1a; 题目&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标…

实现扫码登录

扫码登录是如何实现的&#xff1f; 二维码信息里主要包括唯一的二维码ID,过期的时间&#xff0c;还有扫描状态&#xff1a;未扫描、已扫描、已失效。 扫码登录流程 用户打开网站登录页面的时候&#xff0c;浏览器会向二维码服务器发送一个获取登录二维码的请求。二维码服务器收…

让Elasticsearch飞起来!百亿级实时查询优化实战

让Elasticsearch飞起来&#xff01;百亿级实时查询优化实战 - 简书 最近的一个项目是风控过程数据实时统计分析和聚合的一个 OLAP 分析监控平台&#xff0c;日流量峰值在 10 到 12 亿上下&#xff0c;每年数据约 4000 亿条&#xff0c;占用空间大概 200T。 面对这样一个数据量…

【Java】内存溢出和内存泄露的区别

目录 概念 内存溢出分类 内存泄漏分类 发生场景以及解决方法 内存溢出 内存泄漏 解决方法 这道题是面试常考的&#xff0c;一定要区分好区别&#xff0c;我之前就是直接认为内存溢出就是内存泄漏了 概念 内存溢出&#xff1a;是指程序在申请内存时&#xff0c;没有足够…

国考省考行测:分析推理,形式逻辑,集合推理,真假推理

国考省考行测&#xff1a;分析推理&#xff0c;形式逻辑 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和…

基于Springboot的视频网站系统的设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的视频网站系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

git diff查看比对两次不同时间点提交的异同

git diff查看比对两次不同时间点提交的异同 用 git diff命令&#xff1a; git diff commit-id-1 commit-id-2 不同commit-id在不同的时间点提交产生&#xff0c;因为也可以认为git diff是比对两个不同时间点的代码异同。 git diff比较不同commit版本的代码文件异同_git diff c…

顺序表的奥秘:高效数据存储与检索

&#x1f37f;顺序表 &#x1f9c0;1、顺序表的实现&#x1f365;1.1 创建顺序表类&#x1f365;1.2 插入操作&#x1f365;1.3 查找操作&#x1f365;1.4 删除操作&#x1f365;1.5 清空操作 &#x1f9c0;2、ArrayList的说明&#x1f9c0;3、ArrayList使用&#x1f365;3.1 A…

Focaler-IoU:更聚焦的IoU损失

摘要 边界框回归在目标检测领域中起着至关重要的作用&#xff0c;而目标检测的定位精度在很大程度上取决于边界框回归的损失函数。现有的研究通过利用边界框之间的几何关系来提高回归性能&#xff0c;而忽略了难易样本分布对边界框回归的影响。本文分析了难易样本分布对回归结…

在linux上进行编译调试

1.相关疑问 1. 为什么在代码里使用了一个未定义过的函数&#xff08;如add()&#xff09;&#xff0c;在编译阶段不会报错&#xff0c;在链接阶段会报错呢&#xff1f; 答&#xff1a;先说几个代码编译的结论&#xff1a; 单个\.c源文件文件被编译成机器码文件时&#xff0c…

DC-Windows备份(23国赛真题)

2023全国职业院校技能大赛网络系统管理赛项–模块B:服务部署(WindowServer2022) 文章目录 题目配置步骤在DC1上备份系统状态到D:\共享文件夹所有用户具有读/写权限验证查看DC1备份成功的截图在InsideCli上查看备份文件(查看文件夹安全属性)题目 在DC1上备份系统状态到D:\,…

Linux实验记录:使用firewalld

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 备注: RHEL8系统中集成了多款防火墙管理工具&#xf…

Qt之QLabel介绍

概述 QLabel是QT界面中的标签类&#xff0c;它从QFrame下继承&#xff0c;QLabel 类代表标签&#xff0c;它是一个用于显示文本或图像的窗口部件。我们主要介绍一下QLabel的一些简单的使用。 设置颜色背景色和字体的颜色大小 字体及颜色 设置文字使用的是setText函数。 QStri…

一文彻底搞懂redis数据结构及应用

文章目录 1. Redis介绍2.五种基本类型2.1 String字符串2.2 List列表2.3 Set集合2.4 Zset有序集合2.5 Hash散列 3. 三种基本类型3.1 Bitmap &#xff08;位存储&#xff09;3.2 HyperLogLogs&#xff08;基数统计&#xff09;3.3 geospatial (地理位置) 4. Stream详解4.1 Stream…

小土堆pytorch学习笔记002

目录 1、TensorBoard的使用 &#xff08;1&#xff09;显示坐标&#xff1a; &#xff08;2&#xff09;显示图片&#xff1a; 2、Transform的使用 3、常见的Transforms &#xff08;1&#xff09;#ToTensor() &#xff08;2&#xff09;# Normalize() &#xff08;3&…

Java基础—面向对象—19static关键字详解、抽象类、接口、N种内部类

1、static关键字 匿名代码块、静态代码块、构造方法 静态代码块是在类加载的时候执行&#xff0c;仅执行一次 匿名代码块在调用构造函数之前 验证如下图&#xff1a; 2、静态导入包&#xff08;可能很多人听都没听过&#xff09; 3、Math是用final关键字的&#xff0c;fina…