zoukankan      html  css  js  c++  java
  • Z与黄焖鸡 增强 二分

    看到最小值最大一般会想到二分。

    二分mid,把a中大于等于mid的看成1,小于mid的看成0。

    对于每一行的0和1,我们能把这一行看成二进制中的一个数,设这个二进制数是c[i]。

    如果能找到两行,这两行的c或运算起来全是1,那mid就是合法的。

    也就是说,对于c[i],如果存在c[j],满足c[j]|(((1<<m)-1)^c[i])=c[j],那就说明mid是合法的。

    处理一个vis数组,vis[i]表示是否存在某一个c[k]满足c[k]|vis[i]=c[k]即可。

    vis的处理可以补位处理

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,l,r,ans;
    const int N=100010,M=16;
    int a[N][M],vis[(1<<15)+10];
    int check(int mid)
    {
    	for(int i=0,maxx=(1<<m)-1;i<=maxx;++i)vis[i]=0;
    	for(int i=1,now;i<=n;++i)
    	{
    		now=0;
    		for(int j=1;j<=m;++j)
    			if(a[i][j]>=mid)now|=1<<(j-1);
    		vis[now]=1;
    	}
    	for(int i=(1<<(m-1))-1;i>=0;--i)
    		for(int j=1;j<=m;++j)
    			if(!(i&(1<<(j-1))))vis[i]|=vis[i|(1<<(j-1))];
    	for(int i=1,now;i<=n;++i)
    	{
    		now=0;
    		for(int j=1;j<=m;++j)
    			if(a[i][j]>=mid)now|=1<<(j-1);
    		if(vis[((1<<m)-1)^now])return 1;
    	}
    	return 0;
    }
    int main()
    {
    	cin>>n>>m;
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)scanf("%d",&a[i][j]);
    	l=-1;r=1e9+1;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(check(mid))
    		{
    			ans=mid;
    			l=mid+1;
    		}
    		else r=mid-1;
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    2015个人年度总结
    矢量图标的使用
    onsrcoll和scrollTop兼容与实现
    我们,曾是阿里宝宝
    linux 基本操作笔记
    认识与学习shell
    两道有趣的面试题
    使用css保持一定宽高比例
    我在 超级课程表 实习的那个月
    3、4月学习总结,如愿阿里前端实习生
  • 原文地址:https://www.cnblogs.com/wljss/p/15720734.html
Copyright © 2011-2022 走看看