CF1288D 题解
思路
遇到最小值的最大,首先想到二分答案。check 怎么写呢?因为 ,所以我们可以状态压缩,在这里 表示 二进制的第 位。如果 则 ,否则 。然后只要判断是否有 按位或上 是否等于 就行,如果有就把答案更新成 。但是 枚举 肯定不行,这是因为 中有巨量重复元素。于是,我们可以把 表示第一个 的下标 ,然后两重循环枚举 ,这下时间复杂度只有 了,不会超时。总时间复杂度 ,时间够了。
代码
# include <bits/stdc++.h>
using namespace std;
int n, m, a[300005][10], t, x, l = 1e9, r, mid, best1 = 1, best2 = 1, vis[270];
bool check () {
for (int i = 0; i <= t; ++ i)
vis[i] = 0;
for (int i = 1; i <= n; ++ i) {
x = 0;
for (int j = 0; j < m; ++ j)
if (a[i][j] >= mid)
x |= 1 << j;
if (! vis[x])
vis[x] = i;
}
for (int i = t; ~i; -- i)
if (vis[i])
for (int j = t; ~j; -- j)
if (vis[j] && (i | j) == t) {
best1 = vis[i], best2 = vis[j];
return 1;
}
return 0;
}
int main () {
ios::sync_with_stdio (0);
cin.tie (0);
cout.tie (0);
cin >> n >> m;
t = (1 << m) - 1;
for (int i = 1; i <= n; ++ i)
for (int j = 0; j < m; ++ j)
cin >> a[i][j], r = max (a[i][j], r), l = min (a[i][j], l);
while (l <= r) {
mid = l + r >> 1;
if (check ())
l = mid + 1;
else
r = mid - 1;
}
cout << best1 << ' ' << best2;
return 0;
}

浙公网安备 33010602011771号