【LuoguP1169 bzoj1057】[ZJOI2007]棋盘制作

【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\n%d\n",a1,a2);
90     return 0;
91 }

 

posted @ 2016-08-19 15:44 拦路雨偏似雪花 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值