【二维前缀和】【CF】L Leverage MDT

【二维前缀和】【CF】L Leverage MDT

题目传送门

image

题意:

  • 条件
    • 可以实现单行的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;
}

原文地址:https://www.cnblogs.com/BeautifulWater/p/15455865.html