zoukankan      html  css  js  c++  java
  • 二分check的妙用

    一般对于不容易正向求解的题,我们往往可以枚举答案并进行check,而对于具有单调性的答案或其映射来说,我们可以二分答案并进行check。

    例题1:

    codeforces 1288 D - Minimax Problem  (传送门)

    题意:

    给定n行 长为m的序列;

    找出任意两行序列,使得 两行序列 所有 两个相同索引的最大值 的最小值最大;

    分析:

    这道题朴素做法是O(n^2) ,但想在规定时间复杂度正向推出此题答案是非常不容易的;

    我们可以考虑枚举 最大的最小值,再用check函数加以检验,

    设当前枚举的答案为x,

    对于比x小的数,令其为0,否则令其为1,最后判断两个序列对应的01串的相或的结果是否为 全1,就能判断这个x是否可能成立(本来 答案是5 ,而x是3,但是相或也能得到 全1,虽然x可能不是题目要求的bi,但是由于要求解最值,所以check成功的最大的x一定是bi),而我们则是要找到这个最大的可能;

    显然,x是否可能成立是具有单调性的,所以可以用二分答案;

    注意,题目的m最大为8,而01排列最多就只有 2^8种,我们可以枚举01排列 进行check,而不是O(n^2)枚举所有序列。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N=1e6+5;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    const double eps=1e-6;
    const long double pi=acos(-1.0L);
    #define ls (i<<1)
    #define rs (i<<1|1)
    #define fi first
    #define se second
    #define pb push_back
    #define mk make_pair
    #define mem(a,b) memset(a,b,sizeof(a))
    LL read()
    {
        LL x=0,t=1;
        char ch;
        while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
        while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
        return x*t;
    }
    int lim,n,m,ansl,ansr;//lim是全1
    int a[N][10],vis[305];
    int judge(int x)
    {
        mem(vis,0);
        for(int i=1;i<=n;i++)
        {
            int t=0;
            for(int j=1;j<=m;j++)
                if(a[i][j]>=x) t|=1<<(j-1);//标记所有01排列
            vis[t]=i;
        }
        for(int i=0;i<=lim;i++)
            for(int j=i;j<=lim;j++)
                if((i|j)==lim&&vis[i]&&vis[j])
                {
                    ansl=vis[i]; ansr=vis[j];
                    return 1;
                }
        return 0;
    }
    int main()
    {
        n=read(),m=read();
        lim=(1<<m)-1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=read();
        int l=0,r=1e9;
        ansl=1,ansr=1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(judge(mid)) l=mid+1;
            else r=mid-1;
        }
        printf("%d %d
    ",ansl,ansr);
        return 0;
    }
  • 相关阅读:
    ASP.NET2.0中创建自定义配置节处理程序(声明性模型) joe
    .Net3.0里的DependencyProperty(1) joe
    详解Javascript匿名函数的使用(转) joe
    Mark:未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值 joe
    设置windows 7 默认登陆帐户 joe
    数据库的回滚
    关于软件开发人员如何提高自己的软件专业技术方面的具体建议
    查询表结构
    readonly 和 const总结
    深入NHibernate映射
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12225769.html
Copyright © 2011-2022 走看看