bzoj 1057: [ZJOI2007]棋盘制作
首先是对于图上所有的棋盘一定属于以下两种类型:
1.黑格行列奇偶性相同,白格不同
2.白格行列奇偶性相同,黑格不同
那么在输入的时候属于第一种情况的赋1,属于第二种情况的赋0
统计最大的1或0矩形和正方形就可以啦。
统计矩形和玉蟾宫是一样的做法,单调栈嘛。
1 #include <cstdio> 2 #include <stack> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 #define N 2008 8 9 int ans1,ans2,n,m,f[N][N],s[N],w[N],top; 10 bool map[N][N]; 11 12 void build() 13 { 14 scanf("%d%d",&n,&m); 15 for (int i = 1;i <= n;i++) 16 for (int j = 1;j <= m;j++) 17 { 18 int a; scanf("%d",&a); 19 if ((i & 1) == (j & 1) && a || (i & 1) != (j & 1) && !a) map[i][j] = 1;//& 优先级低于 ==!! 20 else map[i][j] = 0; 21 } 22 for (int i = 1;i <= n;i++) 23 for (int j = 1;j <= m;j++) 24 if (map[i][j]) f[i][j] = f[i][j-1] + 1; 25 else f[i][j] = 0; 26 } 27 28 void rebuild() 29 { 30 for (int i = 1;i <= n;i++) 31 for (int j = 1;j <= m;j++) 32 // map[i][j] = ~map[i][j]; 不能按位取反!!因为第一位之后的也会取反!! 33 map[i][j] = !map[i][j]; 34 for (int i = 1;i <= n;i++) 35 for (int j = 1;j <= m;j++) 36 if (map[i][j]) f[i][j] = f[i][j-1] + 1; 37 else f[i][j] = 0; 38 } 39 40 inline int sqr(int a) 41 {return (a*a);} 42 43 void work() 44 { 45 for (int j = 1;j <= m;j++) 46 { 47 top = 0; 48 for (int i = 1;i <= n + 1;i++) 49 { 50 int minw = i; 51 while (top && s[top] >= f[i][j]) 52 { 53 ans1 = max(ans1,s[top] * (i - w[top])); 54 ans2 = max(ans2,sqr(min(s[top],i-w[top]))); 55 minw = w[top]; 56 top--; 57 } 58 s[++top] = f[i][j]; w[top] = minw; 59 } 60 } 61 } 62 63 void makeline() 64 {for (int i = 1;i <= m;i++) printf("--");printf("\n");} 65 66 void debug() 67 { 68 makeline(); 69 for (int i = 1;i <= n;i++) 70 { 71 for (int j = 1;j <= m;j++) printf("%d ",map[i][j]); 72 printf("\n"); 73 } 74 makeline(); 75 for (int i = 1;i <= n;i++) 76 { 77 for (int j = 1;j <= m;j++) printf("%d ",f[i][j]); 78 printf("\n"); 79 } 80 } 81 82 int main() 83 { 84 // freopen("input.txt","r",stdin); 85 build(); 86 // debug(); 87 work(); 88 rebuild(); 89 // debug(); 90 work(); 91 printf("%d\n%d\n",ans2,ans1); 92 return 0; 93 }