P8472 [Aya Round 1 G] 咕噜论坛(post)

题目链接

Problem

给定一个矩阵,最多进行 \(k\) 次操作,每次可以把 B 改成 GG 改成 BP 不能改,问最后能得到的最大的颜色相同的子矩阵。

Solution

由于 \(n,m\le500\),所以应该是一个 \(O(n^3)\) 的做法。

我们枚举一个矩阵的最上行 \(x\),最下行 \(y\),最左列和最右列的指针分别为 \(L=1,R=1\),这是就确定了一个矩阵,由于具有单调性,所以我们可以每次判断如果能够在 \(k\) 次操作内将其改成相同矩阵(前缀和预处理),就可以考虑将矩阵加大即 \(R++\),否则 \(L++\)。注意如果当前只有一列,且不合法,并不代表后面也不合法,需要 \(L,R\) 都向后推一列。

注意对于每一个 \(x,y\) 都有最大的 \(L,R\),所以开数组存下这个 \(L,R\),然后你需要记录最大的矩阵面积。

有个坑点,要注意紫名矩阵也算,方法一样。

Code

细节较多,码风较丑,仅供参考。

#include<bits/stdc++.h>
using namespace std;
#define int long long
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=507;
char c[N][N];
int sumb[N][N],sumg[N][N],l[N][N],r[N][N],ans[N][N],anss[N][N],ls[N][N],rs[N][N],ss[N][N];
bool ok=0;
int queryb(int a,int b,int c,int d)
{
	return sumb[c][d]-sumb[c][b-1]-sumb[a-1][d]+sumb[a-1][b-1];
}
int queryg(int a,int b,int c,int d)
{
	return sumg[c][d]-sumg[c][b-1]-sumg[a-1][d]+sumg[a-1][b-1];
}
main()
{
	int n,m,k;
	read(n);read(m);read(k);
	for(int i=1;i<=n;i++)
		scanf("%s",c[i]+1);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		sumb[i][j]=sumb[i-1][j]+sumb[i][j-1]-sumb[i-1][j-1]+(c[i][j]=='B');
		sumg[i][j]=sumg[i-1][j]+sumg[i][j-1]-sumg[i-1][j-1]+(c[i][j]=='G');
	//	cout<<sumb[i][j]<<" "<<sumg[i][j]<<endl;
	}
	for(int i=1;i<=n;i++)
	for(int j=i;j<=n;j++)
	{
		int L=1,R=1;
		while(L<=R&&R<=m)
		{
//			cout<<L<<" "<<R<<endl;
			int s=ans[i][j];
			if((R-L+1)*(j-i+1)-queryb(i,L,j,R)-queryg(i,L,j,R)!=0)
			{
				L++;
				if(L>R&&R<m)R++;
				continue;
			}
			if(min(queryb(i,L,j,R),queryg(i,L,j,R))<=k)
			{
				ans[i][j]=max(ans[i][j],(R-L+1)*(j-i+1));
				if(ans[i][j]>s)l[i][j]=L,r[i][j]=R;R++;
//				printf("ans[%d][%d]=%d,l=%d,r=%d\n",i,j,ans[i][j],l[i][j],r[i][j]);
			}
			else L++;
			if(L>R&&R<m)R++;
		}
	}
	for(int i=1;i<=n;i++)
	for(int j=i;j<=n;j++)
	{
		int L=1,R=1;
		while(L<=R&&R<=m)
		{
			int s=anss[i][j];//cout<<L<<" "<<R<<" "<<(R-L+1)*(j-i+1)-queryb(i,L,j,R)-queryg(i,L,j,R)<<endl;
			if(queryb(i,L,j,R)+queryg(i,L,j,R)==0)
			{
				anss[i][j]=max(anss[i][j],(R-L+1)*(j-i+1));
				if(anss[i][j]>s)ls[i][j]=L,rs[i][j]=R;
				R++;
			}
			else 
			{
				L++;
				if(L>R&&R<m)R++;
				continue;
			}if(L>R&&R<m)R++;
		}
	}
	int sb=0,ansi,ansj;
	for(int i=1;i<=n;i++)
	for(int j=i;j<=n;j++)
	{
		if(sb<ans[i][j])
		{
			ok=0;
			sb=ans[i][j];
			ansi=i,ansj=j;
		}
		
		if(sb<anss[i][j])
		{
			sb=anss[i][j];
			ok=1;
		}
	}
	cout<<sb<<endl;
	//cout<<ansi<<" "<<ansj<<endl;
	if(ok)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(i>=ansi&&i<=ansj&&j>=ls[ansi][ansj]&&j<=rs[ansi][ansj])
					cout<<"P";
				else cout<<c[i][j];
			}
			cout<<endl;
		}
		return 0;
	}
	if(queryb(ansi,l[ansi][ansj],ansj,r[ansi][ansj])<=k)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(i>=ansi&&i<=ansj&&j>=l[ansi][ansj]&&j<=r[ansi][ansj])
					cout<<"G";
				else cout<<c[i][j];
			}
			cout<<endl;
		}
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(i>=ansi&&i<=ansj&&j>=l[ansi][ansj]&&j<=r[ansi][ansj])
					cout<<"B";
				else cout<<c[i][j];
			}
			cout<<endl;
		}
	}
	return 0;
}
posted @ 2022-08-09 09:39  Epoch_L  阅读(37)  评论(0编辑  收藏  举报