Codeforces Problem 333D. Characteristics of Rectangles

D. Characteristics of Rectangles

Time limit per test: 3 seconds
Memory limit per test: 256 megabytes
Gerald found a table consisting of n rows and m columns. As a prominent expert on rectangular tables, he immediately counted the table’s properties, that is, the minimum of the numbers in the corners of the table (minimum of four numbers). However, he did not like the final value — it seemed to be too small. And to make this value larger, he decided to crop the table a little: delete some columns on the left and some on the right, as well as some rows from the top and some from the bottom. Find what the maximum property of the table can be after such cropping. Note that the table should have at least two rows and at least two columns left in the end. The number of cropped rows or columns from each of the four sides can be zero.
Input
The first line contains two space-separated integers n and m (2 ≤ n, m ≤ 1000). The following n lines describe the table. The i-th of these lines lists the space-separated integers ai, 1, ai, 2, …, ai, m (0 ≤ ai, j ≤ 109) — the m numbers standing in the i-th row of the table.
Output
Print the answer to the problem.
Examples
input
2 2
1 2
3 4
output
1
input
3 3
1 0 0
0 1 1
1 0 0
output
0
Note
In the first test case Gerald cannot crop the table — table contains only two rows and only two columns.
In the second test case if we’ll crop the table, the table will contain zero in some corner cell. Also initially it contains two zeros in the corner cells, so the answer is 0.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;

const int MAXN = 1e3 + 10;
int n,m,a[MAXN][MAXN],pos[MAXN];
bool vis[MAXN][MAXN];

bool Check(int val){
    memset(vis,0,sizeof vis );
    memset(pos,0,sizeof pos );
    for(int i=1; i<=n; ++i){
        int Num = 0;
        for(int j=1; j<=m; ++j) if(a[i][j] >= val) pos[++Num] = j;
        for(int j=1; j<=Num; ++j)
            for(int k=1; k<j; ++k){
                if(vis[pos[j]][pos[k]]) return true;
                vis[pos[j]][pos[k]] = true;
            }
    }
    return false;
}

int main(int argc,char *argv[]){
    scanf("%d%d",&n,&m);
    int Min=200000000,Max=0;  
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=m; ++j) scanf("%d",&a[i][j]),Max=max(Max,a[i][j]),Min=min(a[i][j],Min);
    int l = Min - 1, r = Max + 1,Ans;
    while(l <= r){
        int Mid = l + r >>1;
        if(Check(Mid)) l = Mid + 1,Ans = Mid;
        else r = Mid - 1;
    }
    printf("%d\n", Ans);
    return 0;
}

最小值最大,显然要二分答案。
求解性问题转化成判定性问题,即在一个01矩阵中判断是否存在4个为1的点,且能构成边与网格平行的矩形。

  • 枚举每一行,在枚举其中每一对“1”
  • 若这一对“1”,在枚举之前的行时标记过,则满足条件
  • 每两列最多被枚举到1次
  • 时间复杂度 m^2

关于二分答案

int l = ,r = ,Ans;
while(l <= r){
    int Mid = l+r >> 1;
    if(Check(Mid)) l = Mid + 1,Ans = Mid;
    else r = Mid - 1;
}
printf("%d\n",Ans);

腿老师说他这么写还没翻过车,啊,吾等小弟赶紧学着点。。

今天整理了十月一号、二号两天内容,写了两道题,很累了,眼睛有点涩,不写了,休息会。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值