二分搜索

Posted xwww666666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分搜索相关的知识,希望对你有一定的参考价值。

模板

找出最左边的一个,最右边的一个,和长度

注意找左位置时要判断:

1>不可以是字串结尾,不然为0或为空

2>不可以不等于key

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,m;
const int N=100003;
int d[N];
int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i]);
    
    int x;
    while(m--)
    
        scanf("%d",&x);
        int pos1=lower_bound(d+1,d+n+1,x)-d;
        if(pos1>n || d[pos1]!=x)
        
            printf("-1 -1 -1\n");
            continue;
        
        int pos2=upper_bound(d+pos1+1,d+n+1,x)-d;
        
        printf("%d %d %d\n",pos1,pos2-1,pos2-pos1);
    
     
    return 0;
 

例题1

阿弥陀佛数数游戏

N个数字(N<=500000),K(K<=500000)个问题,

每个问题询问从L到R中,到底有多少个数字是KEY值?

数据都是int可以存储的

神仙思路:

题目虽然有两个关键字,但是只求第一个关键字相等的情况,所以可以直接sort

sort以后找到相等区间,再去搞第二关键字就好

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,k;
const int N=500003;
struct node
 
    int v,id;
    bool operator < (const node & o) const
     return v==o.v? id<o.id :v<o.v; 
d[N];

int main()

    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i].v ),d[i].id =i;
    sort(d+1,d+n+1);
    
    int l,r;
    node t;
    while(k--)
    
        scanf("%d%d%d",&l,&r,&t.v );
        t.id =l;
        int pos1=lower_bound(d+1,d+n+1,t)-d;
        if(pos1>n || d[pos1].v !=t.v || d[pos1].id >r)
            printf("0\n");
        else
        
            t.id =r;
            int pos2=upper_bound(d+pos1,d+n+1,t)-d;
            printf("%d\n",pos2-pos1);
        
    
    
    return 0;

例题2

晒衣服

1>贪心

众所周知,堆比sort快(除了我)

#include<cstdio>
#include<cstdlib>
#include<queue>
using namespace std;
priority_queue <int> q;
int n,a,b;
int main()

    scanf("%d%d%d",&n,&a,&b);
    int x;
    for(int i=1;i<=n;i++)
        scanf("%d",&x),q.push(x); 
    
    int t=0;
    while(q.top() > a*t)
    
        x=q.top() -b;
        q.pop() ;
        t++;
        q.push(x); 
    
    printf("%d\n",t);
    return 0;

2>二分搜索答案

二分快速确认答案范围

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a,b;
const int N=500000;
int d[N+3];
bool check(int tm)

    int cnt=tm;
    for(int i=n;i;i--)
    
        if(d[i]<=tm*a)
            return true;
        int t=d[i]-tm*a;
        int nd=(ceil(t/(b*1.0)));
        if(nd>cnt) return false;
        else cnt-=nd;
    
    return true;

int main()

    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++) scanf("%d",&d[i]);
    sort(d+1,d+n+1);
    
    int l=1,r=d[n]/a+1;
    while(l<r)
    
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    
    printf("%d\n",l);
    
    return 0;
 

例题3

有道搜索框

//注意呀:字符串可以都看作数
//只是比大小是左对齐形式罢了
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,q;
const int N=10003;
string s[N],ask;
int pos;
int main()

    cin>>n;//cin和scanf不要混用
    for(int i=0;i<n;i++)
        cin>>s[i];
    sort(s,s+n);
    n=unique(s,s+n)-s;//神仙去重 

    cin>>q; 
    while(q--)
    
        cin>>ask;
        int pos1=lower_bound(s,s+n,ask)-s;
        
        pos=ask.length() ;
        ask[pos-1]++;
        int pos2=lower_bound(s+pos1,s+n,ask)-s;
        
        if(pos1==pos2)//神仙判ask是否为s[pos1]的前缀 
        
            ask[pos-1]--;
            cout<<ask<<endl;
        
        else
        
            for(int i=0;i<8 && pos1+i<pos2;i++)
                cout<<s[pos1+i]<<" ";
            cout<<endl;
        
    
    
    return 0;
#include<cstdio>
#include<cstdlib>
#include<queue>
using namespace std;
//众所周知,堆比sort快 
priority_queue <int> q;
int n,a,b;

int main()

	scanf("%d%d%d",&n,&a,&b);
	int x;
	for(int i=1;i<=n;i++)
		scanf("%d",&x),q.push(x); 
	
	int t=0;
	while(q.top() > a*t)
	
		x=q.top() -b;
		q.pop() ;
		t++;
		q.push(x); 
	
	printf("%d\n",t);
	return 0;

 

以上是关于二分搜索的主要内容,如果未能解决你的问题,请参考以下文章

实现二分搜索树

关于二分搜索 简单左侧区间右侧区间

poj3579 二分搜索+二分查找

二分搜索树(Binary Search Tree)

06-二分搜索树 BST

二分搜索算法