You are given arrays ; each array consists of exactly m integers. We denote the y-th element of the x-th array as .
You have to choose two arrays and (, it is possible that ). After that, you will obtain new array consisting of m integers, such that for every .
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 and () — 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 .
Output
Print two integers and (, it is possible that ) — the indices of the two arrays you have to choose so that the value of 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
對進行二分。
設當前值爲,對於矩陣中的某元素,如果,則矩陣,否則。
以爲例,樣例中的矩陣可以得到矩陣如下:
1 0 1 0 0
0 1 1 0 1
0 0 1 1 1
1 0 0 1 1
0 1 0 1 1
1 1 0 1 0
可以看到,矩陣的第1行和第5行逐列相與結果均爲1,因此對於選擇第1行和第5行得到的序列,。函數就是尋找對於當前是否存在行和行,使得矩陣的第行和第行逐列相與結果均爲。由於,暴力枚舉,會超時,但是由於,因此可以枚舉行,枚舉滿足條件的行,然後檢查是否存在即可。
值得注意的是,由於本題要輸出行號,,而不是輸出。雖然得到了正確的,但是由於跳出二分過程導致的情況沒有更新答案,因此在二分結束後還要的情況。
#include<bits/stdc++.h>
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 3e5 + 10, M = 10;
int a[N][M], n, m, ans1, ans2, now, sta[N];
mii num;
inline void build(int x) {
num.clear();
repi(i, 1, n) {
int res = 0;
repi(j, 0, m - 1)if (a[i][j] >= x)res += 1 << j;
num[res] = i, sta[i] = res;
}
}
bool dfs(int x, int u) {
if (u == m) {
if (num[x]) {
ans1 = now, ans2 = num[x];
return true;
}
return false;
}
if (!((sta[now] >> u) & 1))return dfs(x | (1 << u), u + 1);
else {
if (dfs(x, u + 1))return true;
if (dfs(x ^ (1 << u), u + 1))return true;
return false;
}
}
inline bool check() {
repi(i, 1, n) {
now = i;
if (dfs(0, 0))return true;
}
return false;
}
int main() {
n = qr(), m = qr();
int l = INF, r = 0;
repi(i, 1, n)repi(j, 0, m - 1) {
a[i][j] = qr();
l = min(l, a[i][j]);
r = max(r, a[i][j]);
}
while (l < r) {
int mid = (l + r + 1) >> 1;
build(mid);
check() ? (l = mid) : (r = mid - 1);
}
build(l);
check();
printf("%d %d\n", ans1, ans2);
return 0;
}