大意: 给定01矩阵, m个操作, 操作1翻转一个点, 操作2求边界包含给定点的最大全1子矩阵
暴力枚举矩形高度, 双指针统计答案
#include <iostream> #include <algorithm> #include <math.h> #include <cstdio> #include <set> #include <map> #include <string> #include <vector> #include <string.h> #include <queue> #define PER(i,a,n) for(int i=n;i>=a;--i) #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; const int N = 1e3+10, INF = 0x3f3f3f3f; int n, m, q; int a[N][N], U[N][N], D[N][N], L[N][N], R[N][N]; void init() { REP(i,1,n) REP(j,1,m) if (a[i][j]) { U[i][j]=U[i-1][j]+1; L[i][j]=L[i][j-1]+1; } PER(i,1,n) PER(j,1,m) if (a[i][j]) { D[i][j]=D[i+1][j]+1; R[i][j]=R[i][j+1]+1; } } void update(int x, int y) { a[x][y] ^= 1; REP(i,1,n) U[i][y]=(a[i][y]?U[i-1][y]+1:0); PER(i,1,n) D[i][y]=(a[i][y]?D[i+1][y]+1:0); REP(i,1,m) L[x][i]=(a[x][i]?L[x][i-1]+1:0); PER(i,1,m) R[x][i]=(a[x][i]?R[x][i+1]+1:0); } int query(int x, int y) { int ans = 0, t = U[x][y], l = y, r = y; PER(i,1,U[x][y]) { while (l>1&&U[x][l-1]>=i) --l; while (r<m&&U[x][r+1]>=i) ++r; if (U[x][l]>=i&&U[x][r]>=i) { ans = max(ans, i*(r-l+1)); } } t = D[x][y], l = y, r = y; PER(i,1,D[x][y]) { while (l>1&&D[x][l-1]>=i) --l; while (r<m&&D[x][r+1]>=i) ++r; if (D[x][l]>=i&&D[x][r]>=i) { ans = max(ans, i*(r-l+1)); } } t = L[x][y], l = x, r = x; PER(i,1,L[x][y]) { while (l>1&&L[l-1][y]>=i) --l; while (r<n&&L[r+1][y]>=i) ++r; if (L[l][y]>=i&&L[r][y]>=i) { ans = max(ans, i*(r-l+1)); } } t = R[x][y], l = x, r = x; PER(i,1,R[x][y]) { while (l>1&&R[l-1][y]>=i) --l; while (r<n&&R[r+1][y]>=i) ++r; if (R[l][y]>=i&&R[r][y]>=i) { ans = max(ans, i*(r-l+1)); } } return ans; } int main() { scanf("%d%d%d", &n, &m, &q); REP(i,1,n) REP(j,1,m) scanf("%d", &a[i][j]); init(); REP(i,1,q) { int op, x, y; scanf("%d%d%d", &op, &x, &y); if (op==1) update(x,y); else printf("%d\n", query(x,y)); } }
Nanami's Digital Board CodeForces - 434B (棋盘dp)
原文地址:https://www.cnblogs.com/uid001/p/10436335.html
时间: 2024-10-09 10:20:21