给定 N × M N \times M N × M 的 01 矩阵 A A A 。 选取两行 i , j i, j i , j ,满足对于所有列 m m m ,有 A i [ m ] = 1 A_{i}[m] = 1 A i [ m ] = 1 或 A j [ m ] = 1 A_{j}[m] = 1 A j [ m ] = 1 至少一者成立。 最大化满足 A i [ m ] = 1 A_{i}[m] = 1 A i [ m ] = 1 且 A j [ m ] = 1 A_{j}[m] = 1 A j [ m ] = 1 的列数。 输出所选的 i i i 和 j j j 。若有多种选择,则选择 i i i 最小的对;若 i i i 相同,则选择 j j j 最小的对。 2 ≤ N ≤ 2 × 1 0 5 2 \le N \le 2 \times 10^5 2 ≤ N ≤ 2 × 1 0 5 ,2 ≤ M ≤ 20 2 \le M \le 20 2 ≤ M ≤ 2 0 。给定长度为 N N N 的非负整数数组 A A A ,其中每个元素 0 ≤ A i < 2 M 0 \le A_{i} < 2^M 0 ≤ A i < 2 M 。 选取两个下标 i , j i, j i , j ,满足 A i ∣ A j = 2 M − 1 A_{i} \mid A_{j} = 2^M - 1 A i ∣ A j = 2 M − 1 ,并最大化 popcount ( A i & A j ) \operatorname{popcount}(A_{i} \ \& \ A_{j}) p o p c o u n t ( A i & A j ) 。 若有多种选择,则选择 i i i 最小的对;若 i i i 相同,则选择 j j j 最小的对。 2 ≤ N ≤ 2 × 1 0 5 2 \le N \le 2 \times 10^5 2 ≤ N ≤ 2 × 1 0 5 ,2 ≤ M ≤ 20 2 \le M \le 20 2 ≤ M ≤ 2 0 。特判 A i = A j = 2 M − 1 A_{i}=A_{j}=2^M - 1 A i = A j = 2 M − 1 ,否则一定有 A i ≠ A j A_{i} \neq A_{j} A i = A j 。
为了让 A i ∣ A j = 2 M − 1 A_{i} \mid A_{j} = 2^M - 1 A i ∣ A j = 2 M − 1 ,A j A_{j} A j 必须在 A i A_{i} A i 为 0 的位上全为 1。换句话说,A j A_{j} A j 必须是 A i A_{i} A i 按位取反的超集。维护每个 s s s 的第一次出现下标,做超集和,然后拼接即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 std::vector<std::pair<int , int >> f (1 << M, { inf, inf }); std::vector<int > nb; for (int i = 0 ; i < N; i++) { unsigned mask = A[i]; if (mask == ((1 << M) - 1 )) { nb.push_back (i); } chmin (f[mask], { -std::popcount (mask), i }); } if (nb.size () > 1 ) { std::cout << nb[0 ] + 1 << " " << nb[1 ] + 1 << std::endl; return ; } auto g = f;for (int bit = 0 ; bit < M; bit++) { for (unsigned mask = 0 ; mask < 1 << M; mask++) { if (mask >> bit & 1 ) { chmin (g[mask ^ (1 << bit)], g[mask]); } } } std::array<int , 3> res { inf, inf, inf }; for (unsigned mask = 0 ; mask < 1 << M; mask++) { auto [val1, id1] = f[mask]; auto [val2, id2] = g[((1 << M) - 1 ) ^ mask]; if (id1 != inf && id2 != inf && id1 != id2) { chmin (res, { val1 + val2, id1, id2 }); } } if (res[0 ] == inf) { std::cout << "No" << std::endl; } else { auto [val, id1, id2] = res; if (id1 > id2) { std::swap (id1, id2); } std::cout << id1 + 1 << " " << id2 + 1 << std::endl; }