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=2m1

因为 m m m较小,考虑状压表示一个数组。

数组可以相同,所以 2 m − 1 2^m-1 2m1出现过直接输出。

否则直接二重循环枚举状态 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

D. Minimax Problem Codeforces 1288D

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

Minimax Problem CodeForces - 1288D(二分+状态压缩)

codeforces 1288D. Minimax Problem(二分)

[二分答案][状压] Codeforces 1288D Minimax Problem