zoukankan      html  css  js  c++  java
  • 康复训练之二分

    前言:AFO了一年,重新备战CSP&NOIP,故进行简单的恢复训练,以便能够快速到达TG省二水平

    今天回顾的是二分。

    何时使用二分?

    对一个满足单调性质的问题,如:“使最大值最小”或“使最小值最大”等时,我们可以采用二分答案的方法来解决。

    二分模板是什么?

    
    l=-1,r=N;
    while(l+1!=r){
        m=(l+r)/2;
        if(pd(m)) l=m;
        else r=m;
    }
    return l or r(根据题意来看);
    
    

    此模板包含所有类型,妈妈再也不用担心我边界值搞不清了hhhhh

    简单例题选讲

    T1:[NOIP2015 提高组] 跳石头

    二分答案,判断此答案是否在移除 (M) 块之内可行。

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define REP(i,a,b) for(int i=a;i>=b;i--)
    inline int read(){
        int sum=0,ff=1; char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-') ff=-1;
            ch=getchar();
        }
        while(isdigit(ch))
            sum=sum*10+(ch^48),ch=getchar();
        return sum*ff;
    }
    inline void write(int x){
        if(x==0){
            putchar('0');
            return ;
        }
        char F[200];
        int tmp=x>0?x:-x,cnt=0;
        if(x<0) putchar('-');
        while(tmp>0)
            F[cnt++]=tmp%10+'0',tmp/=10;
        while(cnt>0) putchar(F[--cnt]);
    }
    int a[50005],b[50005],L,N,M;
    bool pd(int x){
        int sum=0;
        FOR(i,1,N+1) b[i]=a[i];
        FOR(i,1,N+1) if(b[i]-b[i-1]<x) sum++,b[i]=b[i-1];
        if(sum<=M) return 1;
        else return 0;
    }
    int main(){
        L=read(),N=read(),M=read();
        if(N==0&&M==0){
            write(L);
            return 0;
        }
        FOR(i,1,N) a[i]=read();
        a[N+1]=L;
        int l=-1,r=L;
        while(l+1!=r){
            int mid=(l+r)/2;
            if(pd(mid)) l=mid;
            else r=mid;
        }
        write(l);
        return 0;
    }
    

    T2:刺杀大使

    简单理解下,发现就是求一条路径上的最大值最小。

    二分套一个 (B/DFS) 即可。

    Code:

    
    
    
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1005;
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define REP(i,a,b) for(int i=a;i>=b;i--)
    inline int read(){
        int sum=0,ff=1; char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-') ff=-1;
            ch=getchar();
        }
        while(isdigit(ch))
            sum=sum*10+(ch^48),ch=getchar();
        return sum*ff;
    }
    inline void write(int x){
        if(x==0){
            putchar('0');
            return ;
        }
        char F[200];
        int tmp=x>0?x:-x,cnt=0;
        if(x<0) putchar('-');
        while(tmp>0)
            F[cnt++]=tmp%10+'0',tmp/=10;
        while(cnt>0) putchar(F[--cnt]);
    }
    int n,m,p[N][N];
    const int dx[]={0,1,0,-1,0};
    const int dy[]={0,0,1,0,-1};
    bool vis[N][N];
    queue<int>x;
    queue<int>y;
    bool pd(int sum){
        memset(vis,0,sizeof vis);
        while(!x.empty()) x.pop(),y.pop();
        vis[1][1]=1;
        x.push(1);
        y.push(1);
        while(!x.empty()){
            int xx=x.front();
            int yy=y.front();
            x.pop();y.pop();
            FOR(i,1,4){
                int X=xx+dx[i],Y=yy+dy[i];
                if(X<1||Y<1||X>n||Y>m||vis[X][Y]||p[X][Y]>sum) continue;
                vis[X][Y]=1;
                if(X==n) return 0;
                x.push(X);
                y.push(Y);
            }
        }
        return 1;
    }
    int main(){
        int l=0,r=0;
        n=read(),m=read();
        FOR(i,1,n) FOR(j,1,m) p[i][j]=read(),r=max(r,p[i][j]);
        while(l+1!=r){
            int mid=(l+r)/2;
            if(pd(mid)) l=mid;
            else r=mid;
        }
        write(r);
        return 0;
    }
    
    

    由于时间关系,二分暂时复习到这里,接下去还会是不是地更新其他内容,敬请期待。

  • 相关阅读:
    openSSH学习笔记(一)
    Socket实例
    TCP/IP详解学习笔记(12)-TCP的超时与重传
    TCP/IP详解学习笔记(11)-TCP交互数据流,成块数据流
    TCP/IP详解学习笔记(10)-TCP连接的建立与中止
    TCP/IP详解学习笔记(8)-DNS域名系统
    TCP/IP详解学习笔记(9)-TCP协议概述
    存储过程的优缺点
    数据字典(转)
    abp viewmodel的写法
  • 原文地址:https://www.cnblogs.com/F-T-Y/p/ErFen.html
Copyright © 2011-2022 走看看