CodeForces 1288 D.Minimax Problem (二分+状压优化)

D.Minimax Problem

You are given n arrays a1, a2, …, an; each array consists of exactly m integers. We denote the y-th element of the x-th array as ax,y.

You have to choose two arrays ai and aj (1≤i,j≤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∈[1,m] bk=max(ai,k,aj,k).

Your goal is to choose i and j so that the value of mink=1mbk is maximum possible.

Input

The first line contains two integers n and m (1≤n≤3⋅105, 1≤m≤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 ax represented by m integers ax,1, ax,2, …, ax,m (0≤ax,y≤109).

Output

Print two integers i and j (1≤i,j≤n, it is possible that i=j) — the indices of the two arrays you have to choose so that the value of mink=1mbk is maximum possible. If there are multiple answers, print any of them.

Example

Input

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

1 5

题意:

给n,m
然后给n个长度为m的数组
你可以任选两个下标i,j (1<=i<=j<=n)
他们可以构造出一个新数组b,其中bk=max(aik,ajk)
即bi为两个数组i位置上的数取max

现在要你选择两个下标i,j
满足构造出的b数组的最小值最大
输出选择的两个下标

思路:

二分:
已经告诉你是最小值最大化了,很容易想到二分
主要是check怎么写,容易想到N^2的强行check,但是显然tle
看了题解学到一手状压写法:
假设当前check(mid),因为m最大只有8
对于每个数组,每个元素如果a[i][j]>=mid,则二进制第j位为1,否则为0
然后就可以用一个状态x存下当前数组a[i],记录状态对应的下标sta[x]=i
暴力O((1<<m)^2)遍历状态for(i)for(j)
如果(i|j)==(1<<m)-1则说明存在两个数组能构造出最小值大于等于mid的数组b
记录下答案sta[i]和sta[j]
不断二分就行了,因为二分是单调的,所以答案会在check的过程中逐渐最优

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=3e5+5;
int a[maxm][10];
int sta[maxm];//(1<<8)只有256
int ansx,ansy;
int n,m;
bool check(int mid){
    for(int i=0;i<(1<<m);i++){//clear
        sta[i]=0;
    }
    for(int i=1;i<=n;i++){
        int x=0;
        for(int j=1;j<=m;j++){
            if(a[i][j]>=mid){
                x|=(1<<(j-1));
            }
        }
        sta[x]=i;
    }
    for(int i=0;i<(1<<m);i++){
        for(int j=i;j<(1<<m);j++){
            if(sta[i]&&sta[j]){//两种状态都存在才进一步判断
                if((i|j)==(1<<m)-1){//如果有可行解
                    ansx=sta[i];//答案更新
                    ansy=sta[j];
                    return 1;
                }
            }
        }
    }
    return 0;
}
signed main(){
    cin>>n>>m;
    int l=1e9,r=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];//1e9
            l=min(l,a[i][j]);
            r=max(r,a[i][j]);
        }
    }
    while(l<=r){//二分过程是单调的,check过程中答案只会更优,不用额外记录mid
        int mid=(l+r)/2;
        if(check(mid)){
            l=mid+1;
        }else{
            r=mid-1;
        }
    }
    cout<<ansx<<' '<<ansy<<endl;
    return 0;
}
发布了364 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/104007364