码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1288D - Minimax Problem(二分,二进制枚举)

时间:2021-04-21 12:04:21      阅读:0      评论:0      收藏:0      [点我收藏+]

标签: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))

CODE:

技术图片
#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;
}
View Code

 

Codeforces 1288D - Minimax Problem(二分,二进制枚举)

标签:bit   splay   mamicode   就是   close   sync   比较   closed   ini   

原文地址:https://www.cnblogs.com/UpMing/p/14677602.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!