MINSUB - Largest Submatrix

时间:2021-03-26 17:05:49

MINSUB - Largest Submatrix

no tags 

You are given an matrix M (consisting of nonnegative integers) and an integer K.  For any submatrix of M' of M define min(M') to be the minimum value of all the entries of M'.  Now your task is simple:  find the maximum value of min(M') where M' is a submatrix of M of area at least K (where the area of a submatrix is equal to the number of rows times the number of columns it has).

Input

The first line contains a single integer T (T ≤ 10) denoting the number of test cases, T test cases follow.  Each test case starts with a line containing three integers, R (R ≤ 1000), C (C ≤ 1000) and K (K ≤ R * C) which represent the number of rows, columns of the matrix and the parameter K.  Then follow R lines each containing C nonnegative integers, representing the elements of the matrix M.  Each element of M is ≤ 10^9

Output

For each test case output two integers:  the maximum value of min(M'), where M' is a submatrix of M of area at least K, and the maximum area of a submatrix which attains the maximum value of min(M').  Output a single space between the two integers.

Example

Input:
2
2 2 2
1 1
1 1
3 3 2
1 2 3
4 5 6
7 8 9 Output:
1 4
8 2
分析:首先二分答案M,其次改写成01矩阵,这样变成求最大的全1子矩阵;
   最大全1子矩阵那么可以单调栈解决;
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=1e3+;
const int N=1e3+;
using namespace std;
ll gcd(ll p,ll q){return q==?p:gcd(q,p%q);}
ll qpow(ll p,ll q){ll f=;while(q){if(q&)f=f*p;p=p*p;q>>=;}return f;}
int n,m,k,t,qu[maxn],a[maxn][maxn],v[maxn][maxn],le[maxn],ret,ma,now;
bool ok(int x)
{
now=;
int i,j;
rep(i,,n)rep(j,,m)v[i][j]=(a[i][j]>=x?v[i-][j]+:);
rep(i,,n)
{
rep(j,,m+)
{
if(!qu[])qu[++qu[]]=v[i][j],le[qu[]]=j;
else if(v[i][j]>qu[qu[]])qu[++qu[]]=v[i][j],le[qu[]]=j;
else if(v[i][j]<qu[qu[]])
{
int tmp;
while(qu[]>=&&v[i][j]<=qu[qu[]])
{
now=max(now,(j-le[qu[]])*qu[qu[]]);
tmp=le[qu[]];
qu[]--;
}
qu[++qu[]]=v[i][j];
le[qu[]]=tmp;
}
}
qu[]--;
}
return now>=k;
}
int main()
{
int i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
rep(i,,n)rep(j,,m)scanf("%d",&a[i][j]);
int l=,r=1e9;
while(l<=r)
{
int mid=l+r>>;
if(ok(mid))ret=mid,ma=now,l=mid+;
else r=mid-;
}
printf("%d %d\n",ret,ma);
}
return ;
}