You are given n n n arrays a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an; each array consists of exactly m m m integers. We denote the y y y-th element of the x x x-th array as a x , y a_{x,y} ax,y.
You have to choose two arrays a i a_i ai and a j a_j aj ( 1 ≤ i , j ≤ n 1≤i,j≤n 1≤i,j≤n, it is possible that i = j i=j i=j). After that, you will obtain a new array b b b consisting of m integers, such that for every k ∈ [ 1 , m ] k∈[1,m] k∈[1,m] b k = m a x ( a i , k , a j , k b_k=max(a_{i,k},a_{j,k} bk=max(ai,k,aj,k).
Your goal is to choose i i i and j j j so that the value of min k = 1 m b k \min \limits_{k = 1}^{m} b_k k=1minmbk is maximum possible.
Input
The first line contains two integers n n n and m m m ( 1 ≤ n ≤ 3 ⋅ 1 0 5 , 1 ≤ m ≤ 8 1≤n≤3⋅10^5, 1≤m≤8 1≤n≤3⋅105,1≤m≤8) — the number of arrays and the number of elements in each array, respectively.
Then n n n lines follow, the x x x-th line contains the array a x a_x ax represented by m m m integers a x , 1 , a x , 2 , . . . , a x , m a_{x,1}, a_{x,2}, ..., a_{x,m} ax,1,ax,2,...,ax,m ( 0 ≤ a x , y ≤ 109 0≤ax,y≤109 0≤ax,y≤109).
Output
Print two integers i i i and j j j ( 1 ≤ i , j ≤ n 1≤i,j≤n 1≤i,j≤n, it is possible that i = j i=j i=j) — the indices of the two arrays you have to choose so that the value of min k = 1 m b k \min \limits_{k = 1}^{m} b_k k=1minmbk 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
最小值最大化问题,绝大概率是二分。但是二分之后的judge环节怎么弄呢?这就是本题的出彩之处。我们将每一个数组中的大于等于mid的位置设置为1,否则就设置为0。这样我们进行或操作,这样出来的就是取最大值操作了。这样如果两两相或,如果各个位上都是1,就代表着当前的mid就是最小值,然后不断的二分,就可以找到最优解了。
#include <bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
int a[maxn][10];
int n,m,x,y;
int vis[390];
int check(int mid) {
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++) {
int k = 0;
for (int j = 0; j < m; j++) {
if (a[i][j] >= mid) k |= (1 << j);
}
vis[k] = 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 = 0; j < m; j++) {
scanf("%d", &a[i][j]);
}
}
int l = 0, r = 1e9;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1; else r = mid - 1;
}
printf("%d %d\n", x, y);
return 0;
}