Minimax Problem

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 1i,jn, 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 1n3105,1m8) — 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 0ax,y109).

Output

Print two integers i i i and j j j ( 1 ≤ i , j ≤ n 1≤i,j≤n 1i,jn, 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43601103/article/details/112555891