zoukankan      html  css  js  c++  java
  • 二分模板

    我的二分学习极度坎坷,到了现在(大二),遇到二分题,立马跑路,,感觉自己好憨批(看y总板子背不过)。

    最后还是dalao拯救了我,呜呜呜,感动。dalao板子太强了!

    感激!感激!这次我一定要学会,妈妈再也不用担心我不会二分找答案了。

    二分可以解决的问题:找到满足条件的极限值。必须是极限值的一端一定不符合条件(不可以选择),另一端符合 条件

    二分板子:(理解+记忆) 淦!

    找满足条件最小值:找最小的满足的值(大的都满足),所以找的是正确的r,所以输出的是r。

    //假设答案可能的范围是 1到n
    int l=1,r=n;
    while(l<r){
        int mid=(l+r)>>1;//中间指针
        if(check(mid)) r=mid;//如果中间的值满足,那么减小r来缩小范围
        else l=mid+1;//否则,增大l,尽量让mid满足。
    }
    cout<<r<<endl;//此时的r即为正确答案。
    

    找满足条件的最大值:找的是满足条件的最大值(小的都满足条件),所以找的是正确的l,所以输出与l有关。

    //假设答案可能的范围是 1到n
    int l=2,r=n+1;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid;
    }
    cout<<l-1<<endl;//因为不断更新l的值的时候是让l变成mid+1(此时是mid满足)
    

    例题:

    1385 C. Make It Good(二分!!!)

    题目链接:https://codeforces.com/contest/1385/problem/C

    题目大意:选择删除前缀几个数字,使得剩下的数字可以选择他的第一个数或者最后一个数,选择的数必须比上次选择的数字小或相等,问最少删除几个前缀数字可以成立。

    样例解释:

    第一个样例不需要删除,每次选择第一个数字即可。

    第二个样例需要删除前4个数字:得到 4 5 2 -> 选最后一个 2 -> 选第一个数4 -> 选第一个数 5 得到2 4 5 是非递减的顺序。

    ....

    解题思路:

    删除的前边的数字越多,得到的数组肯定符合,所以要找最小的满足条件的数字n,既可以想到二分。

    使用dalao的第一个板子移动r找最小值即可。

    AC代码:

    #include <iostream>
    using namespace std;
    const int maxn = 2e5+5;
    int a[maxn];
    int n;
    bool check(int x){//从 x位置开始放 
    	int l=x,r=n-1;
    	int now;
    	if(a[l]<a[r]){
    		now=a[l];
    		l++;
    	}else{
    		now=a[r];
    		r--;
    	}
    	while(l<=r){//看选择最左边的数还是最右边的数
    		if(a[l]>=now&&a[r]>=now){//如果都小于上一个数,贪心思想,选择最小的
    			if(a[l]<a[r]){
    				now=a[l];
    				l++;
    			}else{
    				now=a[r];
    				r--;
    			}
    		}else if(a[l]>=now){//只能选择左边的情况
    			now=a[l];
    			l++;		
    		}else if(a[r]>=now){//只能选择右边的情况
    				now=a[r];
    				r--;
    		}else{
    			return false;
    		}
    	}
    	return true;
    }
    
    int main(){
    	int t;
    	cin>>t;
    	while(t--){
    		cin>>n;//找的最小的
    		for(int i=0;i<n;i++){
    			cin>>a[i];
    		} 
    		int l=0,r=n-1;
    		while(l<r){//二分答案
    			int mid=(l+r)/2;
    			if(check(mid)) r=mid;
    			else l=mid+1;
    		}
    		printf("%d
    ",r);
    	}
    	return 0;
    }
    

    冲冲冲!快考试了,不能拉下!

  • 相关阅读:
    linux驱动程序设计的硬件基础,王明学learn
    linux设备驱动概述,王明学learn
    应用程序调试工具gdb,王明学learn
    usb设备驱动描述,王明学learn
    OK6410移植madplay播放器,王明学learn
    bootstrap使用入门(bootstrap4.2.1版本)
    IntelliJ Idea 常用快捷键列表
    javaFX 多窗口编程
    Spring Boot框架入门教程(快速学习版)
    BindingNavigator 控件
  • 原文地址:https://www.cnblogs.com/AC673523745/p/14034032.html
Copyright © 2011-2022 走看看