【基础】二分查找 三分查找

是跟着这篇写的笔记 

二分查找 & 二分答案 万字详解,超多例题,带你学透二分。-CSDN博客


二分相关的知识点们

vector

int bina(vector<int>a,int x){
    int l=0,r=a.size()-1;
    while(l<r){
        int mid=(l+r)>>1;
        if(a[mid]>=x)r=mid;
        else l=mid+1;
    }
    if(a[l]!=x)return -1;
    else return l;
}

lower_bound 大于等于

upper_bound 大于

lower_bound(左,右,x)-数组[0]

,意思是在【左,右)找,减头从而得到下标 

lower_bound(a+1,a+n+1,x)-a;

 lower_bound(a.begin(),a.end(),x)-a.begin();//不能用-a,类型不一样


整数(这里先全用lower_bound力)

P2249 【深基13.例1】查找 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 怎么都过不去

P1102 A-B 数对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

try1:(1)每种减把减数,被减数,差放在结构体里

(2)排序(3)二分 nm

try2: (1)排序(2)对于每个数查找 nm(nm就过不了#3测试点,原来也二分查找右端点nlgn)

灵机一动,用upper_bound 

#include<iostream>
using namespace std;
#include<algorithm>



int main(){
long  long a[200001];
long  long n;scanf("%lld",&n);long long c;scanf("%lld",&c);

for(int i=1;i<=n;i++){
    scanf("%lld",&a[i]);

}
sort(a+1,a+n+1);

long  long ans=0;
for(long long i=1;i<=n-1;i++){
    long  long wei1=lower_bound(a+1,a+n+1,a[i]+c)-a;
    long long wei2=upper_bound(a+1,a+n+1,a[i]+c)-a;
    ans+=wei2-wei1;
}
printf("%lld",ans);

}

try3:(1)统计每个数出现次数(2)对于每个数+c 由于是直接访问,n

错以为2^30是8*2^10,这数组开不到这么大,失败

#include<iostream>
using namespace std;


int book[1073741828]={0};//每个数出现了几遍



int main(){
int a[200001];
int n;cin>>n;int c;cin>>c;

for(int i=1;i<=n;i++){
    cin>>a[i];
    book[a[i]]++;
}
int ans=0;
for(int i=1;i<=n;i++){
        ans+=book[a[i]+c];
}
printf("%d",ans);

}

P1678 烦恼的高考志愿 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

注意比分数线最高的还要高和比最低的还要低的情况,我把0到100001全设为INF

#define INF 0x3f3f3f3f
#include<iostream>
using namespace std;
#include<algorithm>
long mschool[100001];
long nstu[100001];
long m,n;
long solu(long i){
    long mid=lower_bound(mschool+1,mschool+m+1,nstu[i])-mschool;///
    return min(abs(mschool[mid]-nstu[i]),min(abs(mschool[mid-1]-nstu[i]),abs(mschool[mid+1]-nstu[i])));

}


int main(){
long  long ans=0;
cin>>m>>n;
for(long i=0;i<=100001;i++)mschool[i]=INF;
for(long i=1;i<=m;i++)cin>>mschool[i];
sort(mschool+1,mschool+m+1);
for(long i=1;i<=n;i++){
        cin>>nstu[i];
        ans+=solu(i);
}
cout<<ans;

}

789. 数的范围 - AcWing题库

#include<iostream>
using namespace std;
#include<algorithm>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
//测试询问最后一个元素
int main(){
long n;int q;
cin>>n>>q;
int a[100001];
memset(a,INF,sizeof(a));
for(long i=0;i<n;i++)cin>>a[i];
while(q--){
    int k;cin>>k;


    long wei1=lower_bound(a,a+n,k)-a;//这里注意
    long wei2=upper_bound(a,a+n,k)-a;
    if(a[wei1]!=k){
        cout<<-1<<" "<<-1;
    }
    else{
        cout<<wei1<<" "<<wei2-1;
    }
    if(q!=0)cout<<endl;
}


}

P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

也没有看,最后l-1或者r-1两种

至于加一还是减一是样例代出来的

#include<iostream>
using namespace std;
#include<algorithm>

long n;
long long m;
long h_tree[1000001];

bool check(long mid){
long long temp=0;
for(long i=1;i<=n;i++){
    if(h_tree[i]>mid){
        temp+=h_tree[i]-mid;
    }
}
if(temp<m)return true;
else return false;
}
int main(){

cin>>n>>m;
for(int i=1;i<=n;i++)cin>>h_tree[i];

long l=0,r=400000;
while(l<r){
    long mid=(l+r)/2;
    if(check(mid))r=mid;
    else l=mid+1;
}

cout<<r-1;
}

P2440 木材加工 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 check怎么不写反:

if(mid>=ans)

temp+=的分母大

temp<k

这样一步步代,或者mid大,截的每一段大,段数小

#include<iostream>
using namespace std;
#include<algorithm>

int n;long k;
long mu[100001];
bool check(long mid){
    long temp=0;
    for(int i=1;i<=n;i++){
        temp+=mu[i]/mid;

    }
    if(temp<k)return 1;
    else return 0;

}


int main(){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>mu[i];
long l=1,r=100000000;
while(l<r){
    long mid=(l+r)/2;
    if(check(mid))r=mid;
    else l=mid+1;
}
cout<<r-1;
}

P2678 [NOIP2015 提高组] 跳石头 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

没过 

实数

 P1163 银行贷款 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<iostream>
using namespace std;


double w0;
double wper;
int mon;
bool check(double mid){
double temp=w0;//防止改变

for(int i=1;i<=mon;i++){
    temp=temp+temp*mid-wper;
}
if(temp>0)return 1;
return 0;
}

int main(){
cin>>w0>>wper>>mon;

double r=4;
double l=0;
while(r-l>1e-5){//自己定的更精细的区间,之后打印再保留几位
    double mid=(l+r)/2;
    if(check(mid))r=mid;
    else l=mid;
}

printf("%.1lf",l*100);
}

790. 数的三次方根 - AcWing题库

奇函数单调增,正负一起找

#include<iostream>
using namespace std;

double sov;
bool check(double mid){
return mid*mid*mid>sov;

}

int main(){
cin>>sov;
double l=-10000,r=10000;

while(r-l>1e-7){
    double mid=(l+r)/2;
    if(check(mid))r=mid;
    else l=mid;
}
printf("%.6lf",l);
}

P1024 [NOIP2001 提高组] 一元三次方程求解 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

只能说侥幸过,这个给的数据让人不爽

#include<iostream>
using namespace std;


double a,b,c,d;

double f(double x){

return a*x*x*x+b*x*x+c*x+d;
}


bool check(double l,double r,double mid){

if(f(l)*f(mid)<0)return true;
else return false;
}
int main(){
cin>>a>>b>>c>>d;
bool flag=1;
for(int i=-100;i<=99;i++){
    if(f(i)*f(i+1)<=0){

            if(f(i)==0){//左端是根就输出
                if(flag==1)flag=0;
        else cout<<" ";
        printf("%.2lf",1.0*i);
    continue;
            }
            else if(f(i+1)!=0){//为了不多空格
                double l=i,r=i+1;
        while(r-l>1e-5){
            double mid=(l+r)/2;
            if(check(l,r,mid))r=mid;
            else l=mid;
        }
        if(flag==1)flag=0;
        else cout<<" ";
        printf("%.2lf",l);
            }

    }
}

}

三分相关的知识点们

开始看错题了写的数学打表二次函数在区间的最小值

#include<iostream>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        double a,b,c;cin>>a>>b>>c;
        if(a==0){
            if(b>=0)printf("%.4lf",c);
            else printf("%.4lf",1000*b+c);
        }
        else if(a>0){
            if(b>=0)printf("%.4lf",c);//对称轴在0左
            else if(2000*a+b<=0){//对称轴在1000右
                printf("%.4lf",1000*b+c);
            }
            else {
                    printf("%.4lf",c*c-4*a*b);

            }
        }
        else {
            if(1000*a+b<=0)//500左
            {
                printf("%.4lf",1000*b+c);
            }
            else printf("%.4lf",c);//500右
        }

        if(t!=0)cout<<endl;
    }
}

try1:嘿嘿想数学一样求交点,再比较几个交点的最小值

try2:

                                

 3737 -- UmBasketella (poj.org)

Problem - 2438 (hdu.edu.cn)

Problem - 3400 (hdu.edu.cn)

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值