Minimax Problem(二分\bitsmasks)

题目链接:http://codeforces.com/contest/1288/problem/D
参考:https://www.cnblogs.com/switch-waht/p/12197017.html
给定n*m的数组,(1<=n<=3e5,1<=m<=8)
选择2行,相应的列值取max得到新的一行 b = m a x ( a i , a j ) 1 < = i , j < = n b=max(a_i,a_j)(1<=i,j<=n) ,再取 m i n ( b k ) min(b_k) ,求一种选择方案,使该值最大。
题解:二分答案,对于当前的cur值,用一个二进制数标记每一行对于cur的大小,如果>=cur则对应标记为1,否则标记为0。之后,check是否存在2个二进制数,其或运算结果为(1<<m)-1。

#include<bits/stdc++.h>
using namespace std;
const int maxn=300010;

int a[maxn][10];
int n,m;
int x,y;
int vis[300];
bool check(int cur){
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++){
		int res=0;
		for(int j=1;j<=m;j++){
			if(a[i][j]>=cur)
				res|=1<<(j-1);
		}
		vis[res]=i;
	}
	for(int i=0;i<=255;i++){
		for(int j=0;j<=255;j++){
			if(vis[i]&&vis[j]&&((i|j)==((1<<m)-1))){
				x=vis[i];y=vis[j];
				return 1;
			}
		}
	}
	return 0;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
		}
	}
	int l=0,r=1e9,mid;
	while(l<=r){
		mid=(l+r)>>1;
		if(check(mid)){
			l=mid+1;
		}else{
			r=mid-1;
		}
	}
	printf("%d %d\n",x,y);
	return 0;
}

发布了71 篇原创文章 · 获赞 1 · 访问量 2809

猜你喜欢

转载自blog.csdn.net/weixin_43918473/article/details/104108670