【二维前缀和】【CF】L Leverage MDT
题意:
- 条件
- 可以实现单行的01变换;
- 行与行之间的变换是独立的;
- 问题
- 求最长的0方阵或者1方阵的长度平方
参考后的思路整理:
若在某个位置i,j和位置i,j+1两个位置上的字符必然不同,那么不妨定义i,j位置上具有一个疙瘩。
且如果一个方阵没有疙瘩,则说明这个方阵的元素可以全部相同。
这里还是不太严谨,比如以i,j为右下角的方阵是否为单纯的方阵实际上和第j列是否具有疙瘩没有关系(因为这一列的疙瘩代表的是第j列和第j+1列的不同的关系,而第j+1列与当前要探索的方阵没有关系)。
二维前缀和+二分可能长度
二维数组用于存储当前i,j位置具有的疙瘩数
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N = 1e3+100;
int n,m,dp[N][N];
bool check(int x,int y,int len)
{
return (dp[x][y-1]-dp[x][y-len]-dp[x-len][y-1]+dp[x-len][y-len])==0;
}
int main()
{
n = read(), m = read();
char g[n+1][m+1];
for(int i = 1; i<=n;i++)
cin>>g[i]+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m-1;j++)
if(g[i][j+1]!=g[i][j]) dp[i][j]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dp[i][j] += dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1];
int ans=0;
for(int i =1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int l=1,r=min(i,j),save;
while(l<=r)
{
int mid = l+r>>1;
if(check(i,j,mid))
save=mid,l=mid+1;
else
r=mid-1;
}
ans=max(ans,save);
}
cout<<ans*ans;
return 0;
}