当前位置: 首页 > 工具软件 > KMid2 > 使用案例 >

Educational Codeforces Round 80 (Rated for Div. 2) D. Minimax Problem

鲁鹏
2023-12-01

题目链接
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 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 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 1n3105, 1 ≤ m ≤ 8 1 \le m \le 8 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, 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 0ax,y109).

Output

Print two integers i i i and j j j ( 1 ≤ i , j ≤ n 1 \le i, j \le 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

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,jmid,则矩阵 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=1minmbkmid。函数 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 1n3105,暴力枚举 i i i j j j会超时,但是由于 1 ≤ m ≤ 8 1≤m≤8 1m8,因此可以枚举行 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;
}
 类似资料: