题解 - CF1200D White Lines

C F 1200 D   W h i t e   L i n e s \mathrm{CF1200D \ White \ Lines} 题解

题目意思

S o l \mathrm{Sol}

  • 前置知识:二维差分
  • 我们首先考虑哪个点为选择正方形的左上角会对改行产生贡献
  • 我们对于一行进行考虑,设最左黑格位置为 l l ,最右黑格为 r r ,那么如果 r l + 1 > m r-l+1>m 显然无法做出贡献。当我们把一个以 ( r m + 1 , i m + 1 ) (r-m+1,i-m+1) 为左上角, ( i , l ) (i,l) 为右下角的矩形才会有贡献(我这个考虑了很久,还是 t c l tcl )。
  • 列与行计算贡献方法同理,然后二维前缀和统计最大贡献的位置(选择矩阵左上角)
  • 最后我们只要把原本就完整(全部都是白的)计入答案就好了
  • 代码会做出清晰的解释

C o d e \mathrm{Code}

#include <bits/stdc++.h>
#define pb push_back
using namespace std;

inline int read()
{
	int sum=0,ff=1; char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum*ff;
}

const int N=2e3+5;

int n,m,a[N][N],c[N][N],ans;
char ch[N][N];

int main()
{
	n=read();
	m=read();
	for ( int i=1;i<=n;i++ )
		scanf("%s",ch[i]+1);
	for ( int i=1;i<=n;i++ )
	{
		int l=n+1,r=0;
		for ( int j=1;j<=n;j++ )
			if(ch[i][j]=='B')
			{
				l=min(l,j);
				r=max(r,j);//寻找黑块最左以及最右
			}
		if(l==n+1&&!r) ans++;//全部都是白的
		else 
		{
			if(r-l+1>m) continue;//不合法情况
			int sx=max(1,i-m+1),sy=max(1,r-m+1);
			int ex=i,ey=l;
			a[sx][sy]++;
			a[ex+1][ey+1]++;
			a[sx][ey+1]--;
			a[ex+1][sy]--;//二维差分
		}
	}
	for ( int i=1;i<=n;i++ )//列同理
	{
		int l=n+1,r=0;
		for ( int j=1;j<=n;j++ ) 
			if(ch[j][i]=='B')
			{
				l=min(l,j);
				r=max(r,j);
			}
		if(l==n+1&&!r) ans++;
		else 
		{
			if(r-l+1>m) continue;
			int sy=max(1,i-m+1),sx=max(1,r-m+1);
			int ey=i,ex=l;
			a[sx][sy]++;
			a[ex+1][ey+1]++;
			a[sx][ey+1]--;
			a[ex+1][sy]--;
		}
	}
	for ( int i=1;i<=n;i++ ) 
		for ( int j=1;j<=n;j++ ) 
			c[i][j]+=c[i-1][j]+c[i][j-1]-c[i-1][j-1]+a[i][j];//二位前缀和
	int cwy=0;
	for ( int i=1;i+m-1<=n;i++ ) 
		for ( int j=1;j+m-1<=n;j++ ) 
			cwy=max(cwy,c[i][j]);//寻找贡献最大的选择矩形左上角
	ans+=cwy;
	printf("%d\n",ans);
	return 0;
}
			

猜你喜欢

转载自blog.csdn.net/wangyiyang2/article/details/105282317
今日推荐