D. Minimax Problem(二分&状压)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Minimax Problem(二分&状压)相关的知识,希望对你有一定的参考价值。
D. Minimax Problem(二分&状压)
答案具有二分性。
二分答案 a n s ans ans,将所有 ≥ a n s \\ge ans ≥ans的数置为1,否则置为0。
问题等价为是否存在两个数组 或运算 结果为: 111111 = 2 m − 1 111111=2^m-1 111111=2m−1
因为 m m m较小,考虑状压表示一个数组。
数组可以相同,所以 2 m − 1 2^m-1 2m−1出现过直接输出。
否则直接二重循环枚举状态 4 m 4^m 4m。
时间复杂度: O ( l o g A ( 4 m + n m ) ) O(logA(4^m+nm)) O(logA(4m+nm))
#include<bits/stdc++.h>
using namespace std;
int n, m;
vector<vector<int> > a;
int a1, a2;
bool can(int mid)
{
vector<int> msk(1 << m, -1);
for(int i = 0; i < n; i++)
{
int cur = 0;
for(int j = 0; j < m; j++)
if(a[i][j] >= mid)
cur ^= (1 << j);
msk[cur] = i;
}
if(msk[(1 << m) - 1] != -1)
{
a1 = a2 = msk[(1 << m) - 1];
return true;
}
for(int i = 0; i < (1 << m); i++)
for(int j = 0; j < (1 << m); j++)
if(msk[i] != -1 && msk[j] != -1 && (i | j) == (1 << m) - 1)
{
a1 = msk[i];
a2 = msk[j];
return true;
}
return false;
}
int main()
{
scanf("%d %d", &n, &m);
a.resize(n, vector<int>(m));
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
int lf = 0;
int rg = int(1e9) + 43;
while(rg - lf > 1)
{
int m = (lf + rg) / 2;
if(can(m))
lf = m;
else
rg = m;
}
assert(can(lf));
printf("%d %d\\n", a1 + 1, a2 + 1);
}
以上是关于D. Minimax Problem(二分&状压)的主要内容,如果未能解决你的问题,请参考以下文章
D. Minimax Problem Codeforces 1288D
Educational Codeforces Round 80 (Rated for Div. 2) D. Minimax Problem
Minimax Problem CodeForces - 1288D(二分+状态压缩)