zoukankan      html  css  js  c++  java
  • [ZJOI2007] 棋盘制作

    类型:单调栈

    传送门:>Here<

    题意:给出一个$01$矩阵,求$01$相间的最大子正方形和最大子矩阵

    解题思路

    首先考虑如果要求的不是$01$相间而是全$1$的怎么做?那就和上一题一样了,预处理$p[i][j]$。特判正方形(取较短边)

    那么只需要把问题转化为全$1$矩阵即可。思考黑白相间矩阵的特性:无非两种情况,肯定有一种颜色,满足它的格子的坐标要么全是偶数,要么全是奇数

    于是我们只需要在读入的过程中把坐标都是偶数或奇数的格子进行异或。然后对黑色和白色分别做一遍单调栈统计最大子矩形即可

    Code

    由于$p$数组需要处理两次,第二次不能受到第一次的影响。因此需要把不能取的重新置为0

    /*By DennyQi 2018.8.18*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 10010;
    const int MAXM = 27010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x<<3) + (x<<1) + c - '0', c = getchar();return x * w;
    }
    int N,M,ans1,ans2,top,cnt,tmp;
    int a[2010][2010],h[2010],w[2010],p[2010][2010];
    inline void Solve(){
        for(int i = 1; i <= N; ++i){
            top = 0;
            for(int j = 1; j <= M; ++j){
                if(!top || p[i][j] > h[top]){
                    h[++top] = p[i][j];
                    w[top] = 1;
                }
                else{
                    cnt = 0;
                    while(top > 0 && p[i][j] <= h[top]){
                        cnt += w[top];
                        ans2 = Max(ans2, h[top] * cnt);
                        tmp = Min(cnt, h[top]);
                        ans1 = Max(ans1, tmp*tmp);
                        --top;
                    }
                    h[++top] = p[i][j];
                    w[top] = cnt + 1;
                }
            }
            cnt = 0;
            while(top > 0){
                cnt += w[top];
                ans2 = Max(ans2, h[top] * cnt);
                tmp = Min(cnt, h[top]);
                ans1 = Max(ans1, tmp*tmp);
                --top;
            }
        }
    }
    int main(){
        N=r,M=r;
        for(int i = 1; i <= N; ++i){
            for(int j = 1; j <= M; ++j){
                a[i][j]=r;
                if(((i&1)&&(j&1)) || ((!(i&1))&&(!(j&1)))){
                    a[i][j] ^= 1;
                } 
                if(!a[i][j]){
                    p[i][j] = p[i-1][j] + 1;
                }
                else{
                    p[i][j] = 0;
                }
            }
        }
        Solve();
        for(int i = 1; i <= N; ++i){
            for(int j = 1; j <= M; ++j){
                if(a[i][j]){
                    p[i][j] = p[i-1][j] + 1;
                }
                else{
                    p[i][j] = 0;
                }
            }
        }
        Solve();
        printf("%d
    %d
    ",ans1,ans2);
        return 0;
    }
  • 相关阅读:
    Opencv 图像矩
    Opencv Convex Hull (凸包)
    Opencv 发现轮廓 findContours
    Opencv Match Template(轮廓匹配)
    python操作mysql数据库的常用方法使用详解
    mongodb数据库集群及sharding分片配置
    mongodb数据库安装及常见操作
    windows下搭建eclipse关于python的开发环境及初始化参数配置
    python环境下使用tab自动补全命令
    ubuntu系统初始化网络及mysql配置
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9497619.html
Copyright © 2011-2022 走看看