悬线法需要维护三个数组,L[n][m],R[n][m],H[n][m]。
以 Luogu P1169 棋盘制作为例。
(图源自洛谷https://www.luogu.com.cn/blog/RPdreamer/#,侵删)
如果把 L[n][m] 和 H[n][m] 放在一起维护,例如
上图蓝色部分的 L[i][j-1] 已经变为 min(L[i][j-1], L[i-1][j]),这样就无法从蓝色部分得到最大相同元素子矩阵。
把 R[i][j] 和 H[i][j] 放在一起维护也是一样的。
“Shopee杯” e起来编程暨武汉大学2020年大学生程序设计大赛(网络预选赛)D题同理。
正解代码
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int t, n, m; 5 char maze[2020][2020]; 6 int up[2020][2020], l[2020][2020], r[2020][2020]; 7 8 int main() 9 { 10 scanf("%d", &t); 11 while(t--) { 12 scanf("%d %d", &n, &m); 13 for(int i = 1; i <= n; i++) 14 scanf("%s", maze[i]+1); 15 int ans = 1; 16 for(int i = 1; i <= n; i++) { 17 for(int j = 1; j <= m; j++) 18 if(maze[i][j] == maze[i][j-1]) 19 l[i][j] = l[i][j-1]; 20 else 21 l[i][j] = j; 22 for(int j = m; j > 0; j--) { 23 if(maze[i][j] == maze[i][j+1]) 24 r[i][j] = r[i][j+1]; 25 else 26 r[i][j] = j; 27 /*if(maze[i][j] == maze[i-1][j]) { 28 up[i][j] = up[i-1][j]+1; 29 l[i][j] = max(l[i][j], l[i-1][j]); 30 r[i][j] = min(r[i][j], r[i-1][j]); 31 } else { 32 up[i][j] = 1; 33 } 34 ans = max(ans, min(r[i][j]-l[i][j]+1, up[i][j]));*/ 35 } 36 } 37 for(int i = 1; i <= n; i++) 38 for(int j = 1; j <= m; j++) 39 if(maze[i][j] == maze[i-1][j]) { 40 up[i][j] = up[i-1][j]+1; 41 l[i][j] = max(l[i][j], l[i-1][j]); 42 r[i][j] = min(r[i][j], r[i-1][j]); 43 ans = max(ans, min(r[i][j]-l[i][j]+1, up[i][j])); 44 } else { 45 up[i][j] = 1; 46 } 47 printf("%d ", ans); 48 /*for(int i = 1; i <= n; i++) { 49 for(int j = 1; j <= m; j++) 50 printf("%d/%d/%d ", up[i][j], l[i][j], r[i][j]); 51 puts(""); 52 }*/ 53 } 54 return 0; 55 }