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

题目链接:http://codeforces.com/problemset/problem/1288/D

D. Minimax Problem
time limit per test
5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

You are given $$$n$$$ arrays $$$a_1$$$, $$$a_2$$$, ..., $$$a_n$$$; each array consists of exactly $$$m$$$ integers. We denote the $$$y$$$-th element of the $$$x$$$-th array as $$$a_{x, y}$$$.

You have to choose two arrays $$$a_i$$$ and $$$a_j$$$ ($$$1 \le i, j \le n$$$, it is possible that $$$i = j$$$). After that, you will obtain a new array $$$b$$$ consisting of $$$m$$$ integers, such that for every $$$k \in [1, m]$$$ $$$b_k = \max(a_{i, k}, a_{j, k})$$$.

Your goal is to choose $$$i$$$ and $$$j$$$ so that the value of $$$\min \limits_{k = 1}^{m} b_k$$$ is maximum possible.

Input

The first line contains two integers $$$n$$$ and $$$m$$$ ($$$1 \le n \le 3 \cdot 10^5$$$, $$$1 \le m \le 8$$$) — the number of arrays and the number of elements in each array, respectively.

Then $$$n$$$ lines follow, the $$$x$$$-th line contains the array $$$a_x$$$ represented by $$$m$$$ integers $$$a_{x, 1}$$$, $$$a_{x, 2}$$$, ..., $$$a_{x, m}$$$ ($$$0 \le a_{x, y} \le 10^9$$$).

Output

Print two integers $$$i$$$ and $$$j$$$ ($$$1 \le i, j \le n$$$, it is possible that $$$i = j$$$) — the indices of the two arrays you have to choose so that the value of $$$\min \limits_{k = 1}^{m} b_k$$$ is maximum possible. If there are multiple answers, print any of them.

Example
input
Copy
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
Copy
1 5

 题目大意:给你n个长度为m的数组。可以选两个下标i,j(1<=i<=j<=n)。构造成一个新的数组bi=max(aik,ajk). 要求你选择两个下标构成的新数组的最小值最大,然后输出这两个下标

思路:自己想了很久,没有想出怎么降下复杂度,也想过二分,但是也不知道怎么把复杂度降下来,题解是这样的:

对于二分出来的数,我们遍历一遍所有的行,对于每一行中的每个数,如果这个数大于当前的数,把该位置位1,这样我们会得到一个值num ,这也就是该行哪些位大于当前数,

两行合并的话,也很简单,直接或(|)就行了 ,为1的还是为1,只要两行有一行为1就行了。最后只要遍历一遍0-(1<<M)就行了,如果选出来的两个num 或操作之后

得到的数为(1<<M)-1,代表每一位都为1,也就是每一位都大于等于当前选出来的数,那么这个二分值就是合法的。

看代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
#include<map>
#include<queue>
using namespace std;
typedef long long LL;
#define sc1(a) scanf("%lld",&a)
#define pf1(a) printf("%lld\n",a)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int INF=1e9+7;
const int maxn=3e5+5;
const int maxv=1e6+5;
const int mod=998244353;
const int ba=3e5;
LL a[maxn][10];
LL vis[maxn];
LL ans1,ans2;
LL N,M;
bool judge(LL x)
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=N;i++) //压缩
    {
        LL num=0;
        for(int j=1;j<=M;j++)
        {
            if(a[i][j]>=x) //证明这一位有效
            {
                num+=(1<<(j-1));
            }
        }
        vis[num]=i;//
    }
    for(int i=0;i<(1<<M);i++)//暴力压缩后的数
    {
        for(int j=0;j<(1<<M);j++)
        {
            if(vis[i]&&vis[j]&&(i|j)==(1<<M)-1)
            {
                ans1=vis[i];
                ans2=vis[j];
                return true;
            }
        }
    }
    return false;
}
int main()
{
//    freopen("in.txt","r",stdin);
    sc1(N);sc1(M);
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=M;j++)
        {
            sc1(a[i][j]);
        }
    }
    LL l=0,r=1e9;
    while(l<=r)
    {
        LL mid=(l+r)>>1;
        if(judge(mid))
        {
            l=mid+1;
        }
        else r=mid-1;
    }
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}
/**

*/

 

 

posted @ 2020-02-03 14:58  执||念  阅读(210)  评论(0编辑  收藏  举报