Codeforces Problem 333D. Characteristics of Rectangles

来源:互联网 发布:squid nginx 编辑:程序博客网 时间:2024/06/08 18:51

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