• 【LuoguP1169 bzoj1057】[ZJOI2007]棋盘制作


     

     

    首先把矩阵转化一下,把横纵坐标和为偶数点的值取反,这样就转化成求最大的'0'或'1'矩阵。

    这道题每个数字是在格子内的,不能在边界包含障碍点。

    求最大的0矩阵时,把1作为障碍点。求1同理。

    然后求最接近的就可以用树状数组求解啦~

     

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 const int N=2100,Inf=(int)1e9;
     9 int n,m,a1,a2;
    10 int a[N][N],l[N][N],r[N][N],last[N][N],cl[N][N],cr[N][N];
    11 
    12 
    13 int minn(int x,int y){return x<y ? x:y;}
    14 int maxx(int x,int y){return x>y ? x:y;}
    15 
    16 void add(int x,int y,int d)
    17 {
    18     for(int i=y;i<=m;i+=(i&(-i))) cl[x][i]=maxx(cl[x][i],d);
    19     for(int i=y;i>=1;i-=(i&(-i))) cr[x][i]=minn(cr[x][i],d);
    20 }
    21 
    22 int get(int x,int y,int tmp)
    23 {
    24     if(tmp==0)
    25     {
    26         int ans=0;
    27         for(int i=y-1;i>=1;i-=(i&(-i))) ans=maxx(ans,cl[x][i]);
    28         if(ans==0) return 1;
    29         else return ans+1;
    30     }
    31     else
    32     {
    33         int ans=Inf;
    34         for(int i=y+1;i<=m;i+=(i&(-i))) ans=minn(ans,cr[x][i]);
    35         if(ans>=Inf) return m;
    36         else return ans-1;
    37     }
    38 }
    39 
    40 void solve(int tmp)
    41 {
    42     memset(cl,0,sizeof(cl));
    43     memset(cr,63,sizeof(cr));
    44     for(int i=1;i<=n;i++)
    45         for(int j=1;j<=m;j++)
    46         {
    47             if(a[i][j]==tmp) add(i,j,j);
    48         }
    49     memset(l[0],0,sizeof(l[0]));
    50     memset(r[0],63,sizeof(r[0]));
    51     for(int i=1;i<=n;i++)
    52     {
    53         for(int j=1;j<=m;j++)
    54         {
    55             if(a[i][j]==tmp) continue;
    56             if(a[i-1][j]==tmp)
    57             {
    58                 l[i][j]=get(i,j,0);//debug
    59                 r[i][j]=get(i,j,1);//debug
    60                 last[i][j]=i-1;
    61             }
    62             else
    63             {
    64                 l[i][j]=maxx(l[i-1][j],get(i,j,0));
    65                 r[i][j]=minn(r[i-1][j],get(i,j,1));
    66                 last[i][j]=last[i-1][j];
    67             }
    68             int xx=r[i][j]-l[i][j]+1;
    69             int yy=i-last[i][j];
    70             a1=maxx(a1,minn(xx,yy)*minn(xx,yy));
    71             a2=maxx(a2,xx*yy);
    72         }
    73     }
    74 }
    75 
    76 int main()
    77 {
    78     freopen("a.in","r",stdin);
    79     scanf("%d%d",&n,&m);
    80     a1=0;a2=0;
    81     for(int i=1;i<=n;i++)
    82         for(int j=1;j<=m;j++)
    83         {
    84             scanf("%d",&a[i][j]);
    85             if((i+j)%2==0) a[i][j]^=1;
    86         }
    87     solve(1);
    88     solve(0);
    89     printf("%d
    %d
    ",a1,a2);
    90     return 0;
    91 }

     

  • 相关阅读:
    idea主题更换pycharm/intellij
    随机生成n张扑克牌。
    JAVA生成6个1-8的随机数,要求无重复。
    一道简单 的循环
    linux虚拟机互访
    linux中grep命令
    vi和vim编辑器
    文件压缩打包以及备份
    文件内容查询
    目录相关操作
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5787900.html
Copyright © 2020-2023  润新知