zoukankan      html  css  js  c++  java
  • codeforces 1288D. Minimax Problem(二分)

    链接: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 }
  • 相关阅读:
    洛谷 P2294 【[HNOI2005]狡猾的商人】
    洛谷 P5960 【【模板】差分约束算法】/差分约束算法入门
    洛谷 P3916 【图的遍历】
    洛谷 P1347 【排序】
    洛谷 P3243 【[HNOI2015]菜肴制作】
    ES6,ES7,ES8,ES9,ES10新特性一览
    Sass、LESS 和 Stylus区别总结
    MyBatis更新用户信息操作
    MyBatis使用mapper映射文件删除用户信息
    MyBatis使用mapper映射文件添加用户信息
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12210870.html
Copyright © 2011-2022 走看看