Codeforces - Minimax Problem

题目链接:Codeforces - Minimax Problem


最小值最大,首先考虑二分答案。比如当前二分的答案是mid,那么其实数字本身的大小不重要了,我们只关注是否大于等于mid,所以把大于等于的置为1,小于的置为0,那么就可以状态压缩了。只要有两个状态或运算为 1<<m-1 ,那么就是合法的。设 1<<m -1 为s,那么我们可以对每一个状态x找 s^x是否存在,但是有一个问题,就是可能某一个状态是包含 x ^ s而不单单是 s ^ x ,所以我们把包含每一个状态且存在的,都置为1即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=3e5+10;
int n,m,a[N][9],st[1<<8],l,r=1e9,res1=1,res2=1;
inline int check(int mid){
	memset(st,0,sizeof st);
	for(int i=1;i<=n;i++){
		int s=0;
		for(int j=0;j<m;j++)	if(a[i][j]>=mid)	s|=(1<<j);
		st[s]=i;
	}
	for(int i=(1<<m);i>=0;i--){
		for(int j=0;j<m;j++)	if(st[i|(1<<j)])	st[i]=st[i|(1<<j)];
	}
	for(int i=0;i<(1<<m);i++){
		if(st[i]&&st[((1<<m)-1)^i]){
			res1=st[i],res2=st[((1<<m)-1)^i];	return 1;
		}
	}
	return 0;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)	for(int j=0;j<m;j++)	scanf("%d",&a[i][j]);
	while(l<r){
		int mid=l+r+1>>1;
		if(check(mid))	l=mid;
		else	r=mid-1;
	}
	cout<<res1<<' '<<res2;
	return 0;
}
发布了434 篇原创文章 · 获赞 234 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/103988907