• MINSUB


    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+10;
    const int N=1e3+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}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=0;
        int i,j;
        rep(i,1,n)rep(j,1,m)v[i][j]=(a[i][j]>=x?v[i-1][j]+1:0);
        rep(i,1,n)
        {
            rep(j,1,m+1)
            {
                if(!qu[0])qu[++qu[0]]=v[i][j],le[qu[0]]=j;
                else if(v[i][j]>qu[qu[0]])qu[++qu[0]]=v[i][j],le[qu[0]]=j;
                else if(v[i][j]<qu[qu[0]])
                {
                    int tmp;
                    while(qu[0]>=1&&v[i][j]<=qu[qu[0]])
                    {
                        now=max(now,(j-le[qu[0]])*qu[qu[0]]);
                        tmp=le[qu[0]];
                        qu[0]--;
                    }
                    qu[++qu[0]]=v[i][j];
                    le[qu[0]]=tmp;
                }
            }
            qu[0]--;
        }
        return now>=k;
    }
    int main()
    {
        int i,j;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&k);
            rep(i,1,n)rep(j,1,m)scanf("%d",&a[i][j]);
            int l=1,r=1e9;
            while(l<=r)
            {
                int mid=l+r>>1;
                if(ok(mid))ret=mid,ma=now,l=mid+1;
                else r=mid-1;
            }
            printf("%d %d
    ",ret,ma);
        }
        return 0;
    }
  • 相关阅读:
    [转]群控电梯调度算法
    [转] 电梯调度算法总结
    [转]grub2.0和之前版本修复解决方案
    [转]Ubuntu 10.04 编译安装最新版本Linux2.6.34内核
    [转]PS2 键盘工作方式
    [转]个人管理 - 目标管理之前,你会时间管理吗
    [转]ubuntu 下编译内核简单步骤
    [转]关闭Google安全搜索,实现无限制搜索
    [转]Vim 复制粘贴探秘
    [转]Linux文件搜索
  • 原文地址:https://www.cnblogs.com/dyzll/p/6471993.html
Copyright © 2020-2023  润新知