Educational Codeforces Round 80 (Rated for Div. 2) D题

思路:这题有一特点虽然n很大,但是m很小,且最小值最大化–二分

二分check()怎么写?判断每两两数组得出的数组最小值是否可以大于等于mid;

怎么判断是关键----把每一个数组变成一个01串,若这位大于或等于mid则是1,否则是0,那么两个数组得出的数组的最小值要大于或等于mid,那么对这两个二进制作 | 运算,得到的应该是m个1

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 9;
const int N = 3e5+10;
const int inf = 0x3f3f3f3f;
int a[N][M];
int n,m,ans1,ans2;
int num[300];//2^8-1 = 255
bool isOK(int x){
	memset(num,0,sizeof(num));
	for(int i = 0;i < n;i++){
		int sum = 0;
		for(int j = 0;j < m;j++){
			if(a[i][j] >= x) sum+=(1<<j);
		}
		num[sum] = i+1;//记序号 
	}
	for(int i = 0;i < (1<<m);i++){
		for(int j = 0;j < (1<<m);j++){
			if(num[i]&&num[j]&&(i|j)==(1<<m)-1){
				ans1 = num[i];
				ans2 = num[j];
				return true;
			}
		}
	}
	return false;
}
int main(){
	scanf("%d%d",&n,&m);
	int r = -inf,l = inf;
	for(int i = 0;i < n;i++){
		for(int j = 0;j < m;j++){
			scanf("%d",&a[i][j]);
			r = max(r,a[i][j]);
			l = min(l,a[i][j]);
		}
	}
	int ans;
	while(l <= r){
		int mid = l+r>>1;
		if(isOK(mid)){
			l = mid+1;
			ans = mid;
		}else r = mid-1;
	}
	isOK(ans);
	printf("%d %d\n",ans1,ans2);
	return 0;
}
发布了27 篇原创文章 · 获赞 0 · 访问量 343

猜你喜欢

转载自blog.csdn.net/weixin_44083561/article/details/104144988