题解 CF1301E 【Nanosoft】

题解- C F 1301 E   N a n o s o f t CF1301E \ Nanosoft CF1301E Nanosoft

  • 题目意思

    就是让你在一个区域中找到最大符合条件的正方形。

  • S o l Sol Sol

    考虑暴力用前缀和优化来统计答案。

    首先对于每一种颜色做一遍二位前缀和。然后 O ( n × m × min ⁡ ( n , m ) ) O(n \times m \times \min(n,m)) O(n×m×min(n,m))暴力拓展处理出所有边长为 k k k的符合条件的正方形(具体做法看代码)。然后对一个符合条件的正方形的左上角打标记,再对整个矩形中符合条件的位置数做前缀和即可。然后就是 O ( Q × min ⁡ ( n , m ) ) O(Q\times \min(n,m)) O(Q×min(n,m))查询即可。代码里有比较清楚的解释。

  • C o d e Code Code

#include <bits/stdc++.h>
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=505;
const int M=275;

char ch[N][N];
int n,m,Q,f[N][N],g[N][N][5],h[N][N][M],ans;

int main()
{
	n=read();
	m=read();
	Q=read();
	for ( int i=1;i<=n;i++ ) scanf("%s",ch[i]+1);
	for ( int i=1;i<=n;i++ ) 
		for ( int j=1;j<=m;j++ )
		{
			for ( int k=0;k<4;k++ )
				g[i][j][k]=g[i-1][j][k]+g[i][j-1][k]-g[i-1][j-1][k];
			if(ch[i][j]=='R') g[i][j][0]++;
			if(ch[i][j]=='G') g[i][j][1]++;
			if(ch[i][j]=='B') g[i][j][2]++;
			if(ch[i][j]=='Y') g[i][j][3]++;
		}
        //对每种颜色处理前缀和
	for ( int i=1;i<n;i++ ) 
		for ( int j=1;j<m;j++ )
			if(ch[i][j]=='R'&&ch[i+1][j]=='Y'&&ch[i][j+1]=='G'&&ch[i+1][j+1]=='B')
			{
				f[i][j]=1;
				for ( int k=2;k<=min(n,m)/2;k++ ) 
				{
					int x=i-k+1,y=j-k+1;
					int a=i,b=j;
					if(x<1||y<1) break;
                    //注意边界
					if(g[a][b][0]-g[a][y-1][0]-g[x-1][b][0]+g[x-1][y-1][0]!=k*k) break;
					x=i-k+1,y=j+1;
					a=i,b=j+k;
					if(x<1||y<1||a>n||b>m) break;
					if(g[a][b][1]-g[a][y-1][1]-g[x-1][b][1]+g[x-1][y-1][1]!=k*k) break;
					x=i+1,y=j+1;
					a=i+k,b=j+k;
					if(x<1||y<1||a>n||b>m) break;
					if(g[a][b][2]-g[a][y-1][2]-g[x-1][b][2]+g[x-1][y-1][2]!=k*k) break;
					x=i+1,y=j-k+1;
					a=i+k,b=j;
                    //x,y,a,b表示每一块颜色的左上左下,右上右下的位置
					if(x<1||y<1||a>n||b>m) break;
					if(g[a][b][3]-g[a][y-1][3]-g[x-1][b][3]+g[x-1][y-1][3]!=k*k) break;
					f[i-k+1][j-k+1]=k;
                    //对左上角打标记
				}
			}
	for ( int i=1;i<n;i++ ) 
		for ( int j=1;j<m;j++ ) 
			if(f[i][j]) h[i][j][f[i][j]]=1;
            //这个点对于边长k合法的
	for ( int i=1;i<=n;i++ ) 
		for ( int j=1;j<=m;j++ )
			for ( int k=1;k<=min(n,m)/2;k++ ) 
				h[i][j][k]+=h[i-1][j][k]+h[i][j-1][k]-h[i-1][j-1][k];//对合法点数量做前缀和
	while(Q--)
	{
		int x=read(),y=read();
		int xx=read(),yy=read();
		int mx=min(xx-x+1,yy-y+1)/2;
		for ( int k=mx;k>=1;k-- )//打着枚举,找到就结束
		{
			int sx=xx-2*k+1;
			int sy=yy-2*k+1;
			if(h[sx][sy][k]-h[sx][y-1][k]-h[x-1][sy][k]+h[x-1][y-1][k])
			{
				printf("%d\n",k*k*4);
				goto sleep;
			}
		}
		printf("0\n");
		sleep:;
	}
	return 0;
}
		
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
美赛e题通常会要求解决一个实际的工程或管理问题,涉及到建模、数据分析、优化等方面。解题思路通常分为以下几个步骤: 1. 问题理解:首先要仔细阅读题目,理解问题背景、要求和限制条件。明确问题的目标和约束条件是解题的第一步。 2. 建立数学模型:根据问题要求和数据,建立合适的数学模型来描述问题。可能涉及到微积分、概率统计、线性代数等数学知识。模型的建立需要考虑到实际情况和假设条件,尽量简化和抽象问题方便求解。 3. 数据分析:根据所给数据或者自行获取数据,进行数据的处理和分析。可能需要进行数据清洗、统计分析、可视化等工作,以便更好地理解问题和验证模型。 4. 求解优化问题:根据建立的数学模型,可以采用各种优化方法来求解问题。常用的方法包括线性规划、整数规划、动态规划、遗传算法等。在求解的过程中需要注意约束条件的处理和结果的解释。 5. 结果分析和验证:得到结果后,需要进行结果的分析和验证,看是否符合实际情况和问题要求。如果有必要,可以进行灵敏度分析和稳定性分析,探讨模型的鲁棒性和可靠性。 6. 方案优化和改进:根据结果分析的情况,可以对建模和求解过程进行改进和优化,以提高解题的精度和效率。 以上是美赛e题解题思路的一般流程,具体问题具体分析,需要根据具体问题的特点来灵活应对。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值