AcWing 789. 数的范围 二分+模板

https://www.acwing.com/problem/content/791/

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m;
int q[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++) scanf("%d",&q[i]);
    while(m--) {
        int x;
        scanf("%d",&x);
        int l=0,r=n-1;
        while(l<r) {
            int mid=l+r>>1;
            if(q[mid]>=x) r=mid;
            else l=mid+1;
        }
        if(q[l]!=x)  cout<<"-1 -1"<<endl;
        else {
            cout<<l<<" ";
            int l=0,r=n-1;
            while(l<r) {
                int mid=l+r+1>>1;
                if(q[mid]<=x) l=mid;
                else r=mid-1;   //当更新方式为l=mid   r=mid-1
            }
            cout<<l<<endl;
        }
    }
    return 0;
}

模板  这两个模板的区别在于去mid的时候是否+1      平时写的时候可以先不写+1, 然后当更新方式为l=mid, r=min-1时,再写上加1

解释+1:

举例子,因为时向下取整,当l=r-1,如果不补上+1,那么min=l+r+1>>1=l 此时 如果说check时成功的 区间更新为l=mid=l 区间没有发生变化 ,那么下次循环也不会变,所以会形成死循环
当补上+1 mid会变成r 区间更新为l=mid=r 区间会从[l,r] 变成[r,r] 就不会发生死循环

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}
 //整数二分 

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/11746912.html

时间: 2024-11-09 00:39:22

AcWing 789. 数的范围 二分+模板的相关文章

Aizu ITP2_6_A(二分模板)

For a given sequence $A = \{a_0, a_1, ..., a_{n-1}\}$ which is sorted by ascending order, find a specific value $k$ given as a query. Input The input is given in the following format. $n$ $a_0 \; a_1 \; ,..., \; a_{n-1}$ $q$ $k_1$ $k_2$ : $k_q$ The n

Honk&#39;s pool(二分模板题)

题意:有n个水池,每个水池有a[i]单位水,有k次操作,每次操作将水量最多的水池减少一单位水,水量最少的水池增加一单位水,问最后水量最大的水池和水量最少的水池相差的水量. 思路:二分最后的最大水量和最小水量,特别的,模拟一下可以发现如果总水量sum%n==0,则最大值的下界和最小值的上界均为sum/n,若sum%n!=0,则最大值的下界为sum/n+1,最小值上界为sum/n.二分时注意选取区间是左闭右开还是左开右闭. #include <iostream> #include <algo

二分模板// The Frog&#39;s Games +Aggressive cows

  二分的情况不同所输出的模板也不同列如下面两个题目                                                    The Frog's Games   代码如下               //二分专练                                                #include <stdio.h> //lower_bound大于等于它的第一个数                                     

二分模板

从卿学姐那里偷来的模板 (整数二分  待更新更加高级的 int left = 0,ri =maxn; while (left <= ri) { int mid = (left + ri)/2; if( check(mid) ) ans=mid,left = mid+1; else ri= mid-1; } cout << ans <<endl;

51nod 1001 数组中和等于K的数对【二分查找/排序】

1001 数组中和等于K的数对 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K的数对.例如K = 8,数组A:{-1,6,5,3,4,2,9,0,8},所有和等于8的数对包括(-1,9),(0,8),(2,6),(3,5). Input 第1行:用空格隔开的2个数,K N,N为A数组的长度.(2 <= N <= 50000,-10^9 <= K <

51nod 1001_数组中和等于K的数对_二分

题目描述 给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K的数对.例如K = 8,数组A:{-1,6,5,3,4,2,9,0,8},所有和等于8的数对包括(-1,9),(0,8),(2,6),(3,5). 思路 枚举一个二分一个,很优秀. #include <stdio.h> #include <iostream> #include <string> #include <cstring> #include <alg

HDU1688 Sightseeing(SPFA 求最短路与次短路的路径条数)可用作模板

Sightseeing Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 718    Accepted Submission(s): 293 Problem Description Tour operator Your Personal Holiday organises guided bus trips across the Bene

【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分

题目描述 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助. 输入 输入文件第一行包含两个整数N和M. 第二行N个整数,表示初始队列中弹珠的颜色. 接下来M行,每行的形式为"Q L R"或"R x c","Q L R&quo

[BZOJ1594] [Usaco2008 Jan]猜数游戏(二分 + 并查集)

传送门 题中重要信息,每堆草的数量都不一样. 可以思考一下,什么情况下才会出现矛盾. 1.如果两个区间的最小值一样,但是这两个区间没有交集,那么就出现矛盾. 2.如果两个区间的最小值一样,并且这两个区间有交集,那么这个最小值一定在交集中,但是如果这个交集被某个最小值较大的区间,或是一些最小值较大的区间的并集包含,那么也是矛盾的. 可以二分答案,将这些区间按照最小值从大到小排序,然后可以用线段树维护,也可以用并查集来搞. 下面是用并查集来搞的. 每到一个区间,可以将[l,r]中的f变成r+1,如果