CF Round80 D Minimax Problem 二分+二进制

D. Minimax Problem
time limit per test
5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

You are given n
arrays a1, a2, …, an; each array consists of exactly m integers. We denote the y-th element of the x-th array as ax,y

.

You have to choose two arrays ai
and aj (1≤i,j≤n, it is possible that i=j). After that, you will obtain a new array b consisting of m integers, such that for every k∈[1,m] bk=max(ai,k,aj,k)

.

Your goal is to choose i
and j so that the value of mink=1mbk

is maximum possible.
Input

The first line contains two integers n
and m (1≤n≤3⋅105, 1≤m≤8

) — the number of arrays and the number of elements in each array, respectively.

Then n
lines follow, the x-th line contains the array ax represented by m integers ax,1, ax,2, …, ax,m (0≤ax,y≤109

).
Output

Print two integers i
and j (1≤i,j≤n, it is possible that i=j) — the indices of the two arrays you have to choose so that the value of mink=1mbk

is maximum possible. If there are multiple answers, print any of them.
Example
Input

6 5
5 0 3 1 2
1 8 9 1 3
1 2 3 4 5
9 1 0 3 7
2 3 0 6 3
6 4 1 7 0

Output

1 5

这道题的本质就是二分猜答案辅以二进制的应用。 不得不说, 太妙了!

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 3e5 + 10;
int a[maxn][10];
int vis[maxn];
int n, m, ans1, ans2;

bool check(int mid) {
	memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= n; i++) {
		int t = 0;
		for(int j = 1; j <= m; j++) {
			if(a[i][j] >= mid) {
				t |= 1 << (j - 1);
			}
		}
		vis[t] = i;
	}
	int mx = pow(2, m);
	for(int i = 0; i <= mx; i++) {
		for(int j = i; j <= mx; j++) {
			if(vis[i] && vis[j] && ((i | j) == (1 << m) - 1)) {
				ans1 = vis[i], ans2 = vis[j];
				return true;
			}
		}
	}
	return false;
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i = 1; i<= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> a[i][j];
		}
	}
	int l = 0, r = 1e9;
	while(l <= r) {
		int mid = (l + r) >> 1;
//		cout << l << ' ' << r << " " << mid << endl; 
		if(check(mid))
			l = mid + 1;
		else
			r = mid - 1;
	}
	cout << ans1 << " " << ans2 << endl;
	return 0;
}

发布了78 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ln2037/article/details/103993388