题目链接
You are given
n
n
n arrays
a
1
a_1
a1,
a
2
a_2
a2, …,
a
n
a_n
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 \le i, j \le 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 m m integers, such that for every k ∈ [ 1 , m ] k \in [1, m] k∈[1,m] b k = max ( 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 \le n \le 3 \cdot 10^5 1≤n≤3⋅105, 1 ≤ m ≤ 8 1 \le m \le 8 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, 1} ax,1, a x , 2 a_{x, 2} ax,2, …, a x , m a_{x, m} ax,m ( 0 ≤ a x , y ≤ 1 0 9 0 \le a_{x, y} \le 10^9 0≤ax,y≤109).
Output
Print two integers i i i and j j j ( 1 ≤ i , j ≤ n 1 \le i, j \le 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
对
min
k
=
1
m
b
k
\min \limits_{k = 1}^{m} b_k
k=1minmbk进行二分。
设当前值为
m
i
d
mid
mid,对于矩阵中的某元素
a
i
,
j
a_{i,j}
ai,j,如果
a
i
,
j
≥
m
i
d
a_{i,j}≥mid
ai,j≥mid,则矩阵
c
i
,
j
=
1
c_{i,j}=1
ci,j=1,否则
c
i
,
j
=
0
c_{i,j}=0
ci,j=0。
以
m
i
d
=
3
mid=3
mid=3为例,样例中的矩阵
a
a
a可以得到矩阵
c
c
c如下:
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
可以看到,矩阵
c
c
c的第1行和第5行逐列相与结果均为1,因此对于选择第1行和第5行得到的序列
b
b
b,
min
k
=
1
m
b
k
≥
m
i
d
\min \limits_{k = 1}^{m} b_k≥mid
k=1minmbk≥mid。函数
c
h
e
c
k
(
)
check()
check()就是寻找对于当前
m
i
d
mid
mid是否存在行
i
i
i和行
j
j
j,使得矩阵
c
c
c的第
i
i
i行和第
j
j
j行逐列相与结果均为
1
1
1。由于
1
≤
n
≤
3
⋅
1
0
5
1≤n≤3⋅10^5
1≤n≤3⋅105,暴力枚举
i
i
i,
j
j
j会超时,但是由于
1
≤
m
≤
8
1≤m≤8
1≤m≤8,因此可以枚举行
i
i
i,枚举满足条件的行
j
j
j,然后检查是否存在
j
j
j即可。
值得注意的是,由于本题要输出行号
i
i
i,
j
j
j,而不是输出
min
k
=
1
m
b
k
\min \limits_{k = 1}^{m} b_k
k=1minmbk。虽然得到了正确的
min
k
=
1
m
b
k
\min \limits_{k = 1}^{m} b_k
k=1minmbk,但是由于
l
=
r
l=r
l=r跳出二分过程导致
m
i
d
=
min
k
=
1
m
b
k
mid=\min \limits_{k = 1}^{m} b_k
mid=k=1minmbk的情况没有
c
h
e
c
k
(
)
check()
check()更新答案,因此在二分结束后还要
c
h
e
c
k
(
)
check()
check()
m
i
d
=
min
k
=
1
m
b
k
mid=\min \limits_{k = 1}^{m} b_k
mid=k=1minmbk的情况。
#include<bits/stdc++.h>
#define mii unordered_map<int,int>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 3e5 + 10, M = 8;
int a[N][M], n, m, ans1, ans2, now, sta[N];
mii id;
inline void build(int x) {
id.clear();
for (int i = 1, res; i <= n; ++i) {
res = 0;
for (int j = 0; j < m; ++j)
if (a[i][j] >= x)res |= 1 << j;
id[res] = i, sta[i] = res;
}
}
bool dfs(int x, int u) {
if (u == m) {
if (id[x]) {
ans1 = now, ans2 = id[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() {
for (int i = 1; i <= n; ++i) {
now = i;
if (dfs(0, 0))return true;
}
return false;
}
int main() {
scanf("%d%d", &n, &m);
int l = INF, r = 0;
for (int i = 1; i <= n; ++i)
for (int j = 0; j < m; ++j) {
scanf("%d", &a[i][j]);
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;
}