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
inputCopy
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
outputCopy
1 5
题意:给你n个长度为m的数组。可以选两个下标i,j(1<=i<=j<=n)。构造成一个新的数组bi=max(aik,ajk).
要求你选择两个下标构成的新数组的最小值最大,然后输出这两个下标
解析:最小值最大 二分。
因为m<=8,对于每个数组,每个元素a[i][j]>=mid 则二进制第j位为1,否则为0.用一个状态x存在sta[x],然后记录其下标sta[x]=i;
两个for 暴力遍历每个状态 ((1<<m)^2)
如果(i|j)==(1<<m)-1 则说明存在两个数组一定能构成大于等于mid的新数组。
记录答案ansx,ansy
不断二分,答案会逐渐最优。
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
const int M=256;
int a[N][10];
int sta[N];
int ansx,ansy;
int n,m;
bool check(int mid)
{
for(int i=0;i<(1<<m);i++) 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;
}
int 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];
l=min(l,a[i][j]);
r=max(r,a[i][j]);
}
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) l=mid+1;
else r=mid-1;
}
cout<<ansx<<" "<<ansy<<endl;
}