• [BZOJ]1057: [ZJOI2007]棋盘制作


    FallDream dalao随手切 赶紧上他博客学习了一个。

    题目大意:给出一个n*m的01矩阵,求最大的子正方形/矩形,满足任意相邻格子不同。(n,m<=2000)

    思路:把行列坐标相加为偶数的异或上1,题目变成求最大的全为0或1的子正方形/矩形,我们分别处理,预处理出每个格子向右有多少连续的0/1,枚举列,用个单调栈维护和统计答案(维护上升序列),复杂度O(nm)。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 2000
    int n,m,a[MN+5][MN+5],f[MN+5][MN+5],ans1,ans2,q[MN+5],qx[MN+5],qn;
    inline int sqr(int x){return x*x;}
    void solve(int x)
    {
        int i,j;
        for(i=1;i<=n;++i)for(j=m;j;--j)f[i][j]=a[i][j]==x?f[i][j+1]+1:0;
        for(i=1;i<=m;++i)for(j=qn=0;j++<=n;qx[++qn]=f[j][i])
            for(q[qn+1]=j;qn&&f[j][i]<qx[qn];--qn)
                ans1=max(ans1,sqr(min(j-q[qn],qx[qn]))),
                ans2=max(ans2,(j-q[qn])*qx[qn]);
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)a[i][j]=read()^((i+j)&1);
        solve(0);solve(1);
        printf("%d
    %d",ans1,ans2);
    }
  • 相关阅读:
    t
    [持续更新]android stduio的一些小技巧
    Launcher2编译
    数据库
    JavaWeb--会话与状态管理2--cookie 显示最近浏览商品
    JavaWeb--会话与状态管理1--cookie 基础与自动登录
    JavaWeb--MVC案例1-------(6)修改
    JavaWeb--MVC案例1-------(5)添加
    JavaWeb--MVC总结
    JavaWeb--MVC案例1-------(4)删除
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ1057.html
Copyright © 2020-2023  润新知