标签:typedef else 方法 min problem i++ false using printf
链接:https://codeforces.com/contest/1288/problem/D
D. Minimax Problem
题意:给定n个数组,长度为m,从n中数组挑选两个数组,两个数组中的每一位取两者的最大值组成一个新的数组,新数组中的最小值记为c,所有组合中c的最大值
思路:题目中m的范围只有8,数组中元素的范围是1e9,显然m的范围非常特殊,似乎可以把数组用二进制的形式进行状态压缩,这里采用二分答案的方法。二分范围是数组元素最小值到最大值,每次check(mid)一遍,check的时候对于每个数组,用二进制的形式表示出来,数组中小于mid的值用0表示,大于等于mid的用1表示,此时所有的数组都进行了二进制转化,比如一个数组1 2 3 4 5,mid = 3,然后数组就可以状态压缩为0 0 1 1 1 。然后去枚举这些二进制,这样其实最多只会枚举2m × 2m 次,如果枚举的两组二进制相或为11111111,那么说明找到了一组解,返回继续二分,如此过程时间复杂度只有O(n×m + 2m×2m),m的范围只有8。具体看代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 typedef long long ll; 9 const int maxn = 3e5+5; 10 int n,m; 11 int cnt[maxn]; 12 int a[maxn][10]; 13 int num[270]; 14 int ans1,ans2; 15 bool check(int cur){ 16 memset(num,0,sizeof(num));//初始化num数组 17 for(int i = 1;i<=n;i++){ 18 int x = 0; 19 for(int j = m - 1;j>=0;j--){ 20 if(a[i][j]>=cur) x+=(1<<j);///统计满足a[i][j]>=cur的数组的每一位 21 } 22 num[x] = i;//每个数组都转化为二进制 23 } 24 for(int i = 0;i<(1<<m);i++){ 25 for(int j = 0;j<(1<<m);j++){ 26 if(num[i]!=0 && num[j]!=0 && (j|i) == (1<<m)-1){//枚举二进制形式的所有数 27 ans1 = num[i]; 28 ans2 = num[j]; 29 return true; 30 } 31 } 32 } 33 return false; 34 } 35 int main(){ 36 int r = -1,l = 1e9+10; 37 scanf("%d%d",&n,&m); 38 for(int i = 1;i<=n;i++){ 39 for(int j = 0;j<m;j++){ 40 scanf("%d",&a[i][j]); 41 r = max(r,a[i][j]); 42 l = min(l,a[i][j]); 43 } 44 } 45 int mid; 46 while(l<r){//二分答案 47 mid = (l+r+1)/2; 48 if(check(mid)) l = mid ; 49 else r = mid - 1; 50 } 51 check(l); 52 printf("%d %d",ans1,ans2); 53 return 0; 54 }
codeforces 1288D. Minimax Problem(二分)
标签:typedef else 方法 min problem i++ false using printf
原文地址:https://www.cnblogs.com/AaronChang/p/12210870.html