题目链接:http://codeforces.com/problemset/problem/1288/D
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.
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$$$).
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.
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
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 ",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 ",ans1,ans2); return 0; } /** */