标签:bit splay mamicode 就是 close sync 比较 closed ini
最朴素的方法就是暴力枚举两个答案,然后check取一个最大值就ok,时间复杂度O(N^2)
考虑一种比较好的做法
最小值最大化老二分的套路了
我们二分答案
考虑如何check
因为我们二分的mid是最小值,也就是小于这个值的数字,我们一定是用不到的
也就是如果剩下的数字中能够选出两行来,里面的对应位置的max大于这个mid就可以继续扩大答案
考虑一种情况是如果对于第一列的数字,如果我选的两行中,第一列的数字全小于mid肯定不行
至少要有一个大于mid
我们可以把矩阵中大于mid 的数字设成1,小于的设成0
也就是对于一行数字1100101,我只要有一个数字和他或起来的位置全为1,这个mid就是满足条件的
因为这里m很小,我们可以二进制枚举,然后在用一层循环枚举n,(在之前就记录好每个数的位置)check就行了
时间复杂度最坏O((log1e9)*n*(1<<m))
#include "bits/stdc++.h" using namespace std; const int maxn = 3e5 +7 ; typedef long long ll; int a[maxn][10],n,m,max_num,pos[260],num[maxn],ansx,ansy; int ok(int x) { memset(pos, 0 ,sizeof pos); for(int i=1 ;i<=n ;i++) { int temp =0 ; for(int j=1 ;j<=m ;j++) { if(a[i][j]>=x) temp+=1<<(j-1); } num[i] = temp; pos[temp] = i; } for(int i=0 ;i<=max_num;i++) { if(pos[i]==0) continue; for(int j=1 ;j<=n ;j++) { if((num[j]|i) == max_num) { ansx = pos[i]; ansy = j; return 1; } } } return 0; } int main() { ios::sync_with_stdio(false); cin>>n>>m; max_num = 1<<m,max_num--; for(int i=1 ;i<=n ;i++) { for(int j=1 ;j<=m ;j++) { cin>>a[i][j]; } } int l =0 ,r = 1000000000; while(l<=r) { int mid = (l+r)>>1; if(ok(mid)) l = mid+1; else r = mid-1; } cout<<ansx<<" "<<ansy<<endl; return 0; }
Codeforces 1288D - Minimax Problem(二分,二进制枚举)
标签:bit splay mamicode 就是 close sync 比较 closed ini
原文地址:https://www.cnblogs.com/UpMing/p/14677602.html