• BZOJ1057(单调栈 or 悬线法)


    方法一

    • 黑白棋盘拥有性质:(r + c) % 2的值决定颜色
    • 因此把某色全部反转,直接求另一色的最大矩形即可,单调栈的经典问题
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    const int maxn = 2005;
    int n, m, a[maxn][maxn], h[maxn][maxn];
    int ans1, ans2;
    
    void solve(int c) {
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			h[i][j] = (a[i][j] == c) ? h[i][j - 1] + 1 : 0;
    		}
    	}
    	int L[n + 5], R[n + 5];
    	for (int j = 1; j <= m; j++) {
    		vector<int> st;
    		for (int i = 1; i <= n; i++) {
    			while (st.size() && h[st.back()][j] >= h[i][j])	st.pop_back();
    			L[i] = st.size() ? st.back() + 1 : 1;
    			st.emplace_back(i);
    		}
    		st.clear();
    		for (int i = n; i; i--) {
    			while (st.size() && h[st.back()][j] >= h[i][j])	st.pop_back();
    			R[i] = st.size() ? st.back() - 1 : n;
    			st.emplace_back(i);
    		}
    		for (int i = 1; i <= n; i++) {
    			int S = h[i][j] * (R[i] - L[i] + 1);
    			int t = min(h[i][j], R[i] - L[i] + 1);
    			ans1 = max(ans1, t * t);
    			ans2 = max(ans2, S);
    		}
    	}
    }
    
    int main() {
    	scanf("%d %d", &n, &m);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++) {
    			scanf("%d", &a[i][j]);
    			if ((i + j) & 1)
    				a[i][j] ^= 1;
    		}
    	solve(0), solve(1);
    	return !printf("%d
    %d
    ", ans1, ans2);
    }
    

    方法二

    • 悬线法:对每个点求出它合法的矩阵向左向右向上分别能多长,然后更新答案。其中求时肯定不能暴力,要从上一个递推过来
    • 如果高度能从上面递增过来,左右线也要跟上面取min
    • 其实我觉得和方法一思想挺像的……
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 2005;
    int n, m, a[maxn][maxn];
    int h[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
    int ans1, ans2;
    
    int main() {
    	scanf("%d %d", &n, &m);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++)
    			scanf("%d", &a[i][j]);
    
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			if (i > 1 && a[i][j] != a[i][j - 1]) {
    				l[i][j] = l[i][j - 1] + 1;
    			} else	l[i][j] = 1;
    		}
    		for (int j = m; j; --j) {
    			if (j < m && a[i][j] != a[i][j + 1]) {
    				r[i][j] = r[i][j + 1] + 1;
    			} else	r[i][j] = 1;
    		}
    		for (int j = 1; j <= m; j++) {
    			if (i > 1 && a[i][j] != a[i - 1][j]) {
    				h[i][j] = h[i - 1][j] + 1;
    				l[i][j] = min(l[i][j], l[i - 1][j]);
    				r[i][j] = min(r[i][j], r[i - 1][j]);
    			} else	h[i][j] = 1;
    
    			int Len = r[i][j] + l[i][j] - 1;
    			int t = min(Len, h[i][j]);
    			ans1 = max(ans1, t * t);
    			ans2 = max(ans2, Len * h[i][j]);
    		}
    	}
    	return !printf("%d
    %d
    ", ans1, ans2);
    }
    
  • 相关阅读:
    Informix IDS 11系统办理(918考试)认证指南,第6部分:IDS备份和恢复(1)
    Informix IDS 11体系处置(918检验)认证指南,第 4 局部: 性能调优(7)
    我常用网址整理
    System.Insert 插入字符串
    System.Length 获取字符串或数组的长度
    System.New、System.Dispose 为某个指针申请和释放内存
    System.GetMem、System.FreeMem 申请和释放内存
    学习 TList 类的实现[1]
    学习 TList 类的实现[2]
    System.ReallocMem 重新申请内存
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10997584.html
Copyright © 2020-2023  润新知