• Codeforces 1288D Minimax Problem


    Description

    描述

    给出一个 $n$ 行 $m$ 列的数字矩阵 $a$,找出两行 $x, y$,令 $b_j = max(a_{x, j}, a_{y, j})$,试使得 $maxlimits_{1 le j le m}b_j$ 最大,输出选择的 $x, y$,可以相同。

    输入

    第一行是 $n, m(1 le n le 3 cdot 10^5, 1 le m le 8)$。

    后面是一个 $n$ 行 $m$ 列的矩阵 $a$,$0 le a_{i,j} le 10^9$。

    输出

    两个数 $x, y$,表示选取第 $x$ 行和第 $y$ 行,多解输出任意解。

    样例

    输入

    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

    解释

    $b = { 5, 3, 3, 6, 3 }$,最小值是 $3$,没有最小值更大的方案了。

    Solution

    看到要求 最小值的最大值,显然要想到 二分。

    观察到 $m le 8$,是不是可以 二进制压位 呢?答案是肯定的。

    比如我们在判断答案为 $mid$ 是否可行时,我们对每一行定义一个二进制数 $b_i$,这个其实是一个  bitset ,但因为位数太少直接  int  就能实现,当 $a_{i,j} ge mid$ 时,$b_i$ 的左数第 $j$ 位就是 $1$,否则为 $0$。例如,$mid = 3$,$a_i = { 3, 4, 1, 2 }$,那么 $b_i = 1100_{(2)}$。这时,我们将 $t_{b_{i}}  gets i$,表示此状态的来源。

    考虑枚举两个状态 $i, j$,如果 $i, j$ 状态都存在(可以通过先将 $t$ 初始化为 $0$,看 $t_i, t_j$ 是不是 $> 0$ 来实现),然后如果 $i operatorname{or} j = 11dots 11$,那么这两个状态就可以满足我们的需求了(因为这说明每个位置都能找到至少一个 $ge mid$ 的数字),将所选的两行数定为 $t_i$ 和 $t_j$ 即可。

    代码如下,仅供参考:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 3e5 + 5, M = 10;
    int n, m, a[N][M], b[N], t[1 << M], x, y;
    inline bool check(int mid)
    {
    	memset(b, 0, sizeof b);
    	memset(t, 0, sizeof t);
    	for(int i = 1; i <= n; i++)
    	{
    		for(int j = 1; j <= m; j++)
    			b[i] = (b[i] << 1) | (a[i][j] >= mid);
    		t[b[i]] = i;
    	}
    	for(int i = 1; i < (1 << m); i++)
    		for(int j = 1; j < (1 << m); j++)
    			if((i | j) == (1 << m) - 1 && t[i] && t[j])
    			{
    				x = t[i]; y = t[j];
    				return true;
    			}
    	return false;
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin >> n >> m;
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= m; j++)
    			cin >> a[i][j];
    	int lb = -1, rb = 1e9;
    	while(lb < rb)
    	{
    		int mid = lb + rb + 1 >> 1;
    		if(check(mid)) lb = mid;
    		else rb = mid - 1;
    	}
    	cout << x << ' ' << y << endl;
    	return 0;
    }
  • 相关阅读:
    Give root password for maintenance(or press Control-D to continue)
    docker swarm 拉2副本 及磁盘映射
    删除 Docker私有仓库镜像文件
    docker swarm 从私有仓库拉取 创建2个docker副本
    mysqldump 备份导出数据排除某张表
    node递归属性目录结构
    MySql批量更新方法
    npm 发布包
    实例学习Backbone.js(一)
    node.js中log4js的使用
  • 原文地址:https://www.cnblogs.com/syksykCCC/p/CF1288D.html
Copyright © 2020-2023  润新知