首页 > 其他分享 >洛谷题单指南-二分查找与二分答案-P2249 【深基13.例1】查找

洛谷题单指南-二分查找与二分答案-P2249 【深基13.例1】查找

时间:2024-02-28 19:45:42浏览次数:37  
标签:二分 13 int res mid 查找 模版 check

原题链接:https://www.luogu.com.cn/problem/P2249

题意解读:找有序数组中某个数第一次出现的位置,二分模版题,由于是二分板块的第一题,有必要对二分的各种模版进行介绍。

解题思路:

关于二分的一切:

1、二分的本质

二分的本质,是通过某种判定把目标范围划分成两个区间

二分问题通常有两种要求:

a、找绿色范围的起始值 b、找红色范围的结束值

初始给定目标范围的最小、最大值:l、r

取中间值mid = (l + r) / 2

根据某种逻辑check(mid)进行判定mid属于哪个区间

对于要求a:如果属于绿色区间,更新答案,继续在l ~ mid - 1之间寻找;否则在mid + 1 ~ r之间寻找。

对于要求b:如果属于红色区间,更新答案,继续在mid+1 ~ r之间寻找;否则在l ~ mid - 1之间寻找。

因此,二分就有两种模版。

2、整数二分:

模版1:找绿色范围的起始值

int bs1(int l, int r)
{
    int res = -1;
    while(l <= r)
    {
        int mid = (l + r) >> 1; 
        if(check(mid)) 
        {
            res = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    return res;
}

说明:

a、(l + r) >> 1等同于(l + r) / 2,区别在于如果l + r是负数,除以2会向上取整,而整数是向下取整,>> 1的方式就是统一向下取整。

b、check(mid)表示判定mid是符合绿色范围的

模版2:找红色范围的结束值

int bs2(int l, int r)
{
    int res = -1;
    while(l <= r)
    {
        int mid = (l + r) >> 1; 
        if(check(mid)) 
        {
            res = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }
    return res;
}

说明:check(mid)表示判定mid是符合红色范围的

3、实数二分:

模版1:

int bs1(double l, double r)
{
    while(r - l > 1e-8)
    {
        double mid = (l + r) / 1; 
        if(check(mid)) r = mid;
        else l = mid;
    }
    return r;
}

由于实数没有连续性,在更新区间边界的时候,直接用r = mid或l = mid;

另外,实数无法精确判断相等,采用r - l > 1e-8,如果差大于一个很小的数,认为基本相等且r不会在l左边

通常,这个很小的数可以根据题目要求的保存的小数位置确定,例如题目要求保留2位小数,则可以取1e-4,比要求多2位即可。

模版2:

int bs2(double l, double r)
{
    while(r - l > 1e-8)
    {
        double mid = (l + r) / 1; 
        if(check(mid)) l = mid;
        else r = mid;
    }
    return r;
}

其实,对于实数二分,模版1和模版2没有区别,可以在check的时候通过返回值来统一成一套模版。

回到本题:

要找数字第一次出现的位置,显然是找绿色范围的起始值,对应模版1,只不过题目要求如果要找的数不存在则返回-1,在结果返回之前判断一下即可:

if(a[res] == x) return res; else reutrn -1;

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;

int a[N], q, n, m;

int bs(int x)
{
    int l = 1, r = n, res = -1;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(a[mid] >= x) 
        {
            res = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    if(a[res] == x) return res;
    return -1;
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= m; i++) cin >> q, cout << bs(q) << " ";

    return 0;
}

 

标签:二分,13,int,res,mid,查找,模版,check
From: https://www.cnblogs.com/jcwy/p/18041577

相关文章

  • 假期vue学习笔记13 插槽
     <template>  <divclass="category">    <h3>{{title}}分类</h3>    <slot></slot>  </div></template><script>  exportdefault{    name:'Category',    pr......
  • 二分查找——修补木桶
    修补木桶-HihoCoder1362-VirtualJudge(vjudge.net)#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>usingnamespacestd;#defineintlonglong#defineQAQ0constintN=2e5+5,inf=0x3f3f3f3f,mod=1e7+7;int......
  • 2.13
    packagecom.example.myapplication;importandroidx.annotation.Nullable;importandroidx.appcompat.app.AppCompatActivity;importandroid.annotation.SuppressLint;importandroid.app.AlertDialog;importandroid.content.DialogInterface;importandroid.conte......
  • 2.13 密码的修改
    密码的修改<%@pagecontentType="text/html;charset=UTF-8"language="java"%><html><head><title>新密码</title></head><body><divstyle="text-align:center"><formaction="......
  • cf1396d-solution
    CF1396DSolutionlink题面:给你一个\(L\timesL\)的矩形,有\(n\)个点放在不同的格子内,每个点有颜色,共\(k\)种颜色,求有多少个矩形满足其内部含有所有颜色的点,对\(10^9+7\)取模。\(k\len\le2000,L\le10^9\)。首先离散化。看到数据范围说明可以枚举矩形的某个端点或者......
  • cf1340d-solution
    CF1340DSolutionlink手❤玩❤一❤下,答案大概就是所有点的度数最大值。下面证明。首先这个肯定是答案的下界,因为度数最大的点至少被经过了它的度数次。现在考虑构造。对于一棵以\(u\)为根的子树,如果我们能证明第一次到\(u\)的时间是\(t\),最后一次到\(u\)的时间是\(t-......
  • cf1332f-solution
    CF1332FSolutionlink设\(dp_{u,0/1,0/1}\)表示在\(u\)的子树中,节点\(u\)与它父亲的边是否在导出子图中,点\(u\)是否在独立集中,的方案数。\[dp_{u,0,0}\gets\prod_v(dp_{v,0,0}+dp_{v,1,0}+dp_{v,0,1}+dp_{v,1,1})\]\[dp_{u,1,0}\gets\prod_v(dp_{v,0,0}+dp_{v,1,0}+......
  • cf1303g-solution
    CF1303GSolutionlink\(k\)个数\(a_i\)的前缀和的和就是\(\displaystyle\sum_{i=1}^k(k-i+1)a_i\)。这个题可以考虑换一下\(u,v\),那么式子就变成了\(\displaystyle\sum_{i=1}^kia_i\)。注意到要统计树上路径的最值,考虑点分治。考虑上面的式子从\(j\)处断开,那么式子变......
  • [USACO13MAR]Farm Painting S 题解
    看大家好多写的都用了四维偏序,给一个不用偏序的解法。简化一下题目,就是给你\(n\)个矩形,第\(i\)个矩形用\((x1_i,y1_i,x2_i,y2_i)\)表示,问你有多少个\(i\)满足:不存在另一个\(j\)使得\(x1_j\lex1_i\lex2_j\wedgey1_j\ley1_i\ley2_j\)。我们从左到右扫描每一个......
  • CF1392I Kevin and Grid 题解
    题目传送门\(\large\textbf{Statement.}\)给定两个序列\(a,b\),有一个\(n\timesm\)的网格图,每个点\((i,j)\)上有个权值\(a_i+b_j\),每个点和其上、下、左、右方相邻的点有连边。多次询问,每次给一个阈值\(x\),将图分为权值\(<x\)(蓝色)和\(\gex\)(红色)的两种连通块。一......