8-21模拟赛解题报告

呜呜呜~评测机炸锅!模拟赛爆零!!( >﹏<。)


T1.chess

题目大意:给出一个(n imes n)黑白棋盘,求将其中(k imes k)区域的黑棋变成白棋后,全是白棋的行数和列数之和。

这题(n,kle 2000),所以很显然只能使用(O(n^2))算法,所以算每一个点的贡献就成了一个不错的方式。

我们先从行来看,如果一行中有贡献,必要的条件就是两边的黑棋的距离必须小于k,而如果我们只看最两边的黑棋的话,会发现,有贡献的区域(即(k imes k)矩阵左上角在这个区域时答案会加一)是成矩形。所以我么就可以使用二维差分数组,计算答案。具体如下:

设第(i)行最左与最右的黑棋的纵坐标设为(l,r),所以矩阵左上角的纵坐标至少应为(r-k+1),最多不能超过(l),横坐标至少应为(i-k+1),最多不能超过(i)。所以设差分数组为(sum[i][j])

[sum[i-k+1][r-k+1]+1,sum[i-k+1][l+1]-1 ]

[sum[i+1][r-k+1]-1,sum[i+1][l+1]+1 ]

然后算一算(sum)的前缀和取最大值就好了。

要注意的一点就是(i-k+1)等可能会小于(1),要与(1)(max),以及可能会出现一行没有黑棋的情况,要特判。

小结:

解题关键:想到计算贡献与差分维护

芝士点:差分

其实也还是一道思维题啦!

手起,码落:

#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=2005;
int n,k,s,sum[N][N],ans;
char ch[N][N];
int main()
{
	scanf("%d%d",&n,&k);
	for(re int i=1;i<=n;i++)scanf("%s",ch[i]+1);
	for(re int i=1,l,r,yor;i<=n;i++)
	{
		yor=0,l=1,r=n;
		for(re int j=1;j<=n;j++)
		{
			if(ch[i][j]=='B')
			{
				yor=1;
				l=max(l,j-k+1);
				r=min(r,j);
			}
		}
		if(yor==0)s++;
		if(r<l)continue;
		sum[max(i-k+1,1)][l]++;
		sum[max(i-k+1,1)][r+1]--;
		sum[i+1][l]--;
		sum[i+1][r+1]++;
	}
	for(re int i=1,l,r,yor;i<=n;i++)
	{
		yor=0,l=1,r=n;
		for(re int j=1;j<=n;j++)
		{
			if(ch[j][i]=='B')
			{
				yor=1;
				l=max(l,j-k+1);
				r=min(r,j);
			}
		}
		if(yor==0)s++;
		if(r<l)continue;
		sum[l][max(i-k+1,1)]++;
		sum[r+1][max(i-k+1,1)]--;
		sum[l][i+1]--;
		sum[r+1][i+1]++;
	}
//	for(re int i=1;i<=n;i++)
//	{
//		for(re int j=1;j<=n;j++)printf("%d ",sum[i][j]);
//		puts("");
//	}
	for(re int i=1;i<=n;i++)
		for(re int j=1;j<=n;j++)
			sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1],ans=max(ans,sum[i][j]);
	printf("%d",ans+s);
	return 0;
}

T2.sequence

一句话题意:求一个序列分成若干块后的最大极差之和。(极差为最大值减最小值

这题看似简单,其实!也并不难。。

直接上吧,(f[i])表示前(i)个数的最大极差之和。首先,显而易见的一点是:在一个单调序列中间的节点绝对不会是决策点,因为选择端点一定优于中间节点。所以我们就可以把中间节点去掉,直接与(f[i-1])(f[i-2])达到(O(1))转移啦!

要注意这题因为某些不知明的原因,用了一种输入量也是极大的方式生成数据。但代码中还是正常输入。

小结:

解题关键:想到单调序列中间节点非决策点而优化时间。

芝士点:动态规划

感觉最近的思维题好多呀!

手起,码落:

#include<bits/stdc++.h>
#define re register
#define max(x,y) ((x)>(y)?(x):(y))
#define MOD 1073741824
using namespace std;
inline long long read()
{
	re long long x=0,f=1;
	re char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f*=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
	return x*f;
}
const int N=10000005,M=500005;
int len;
long long n,aa[N],ans,a[N],f[N];
bool vis[N];
int main()
{
	n=read();
	for(re int i=1;i<=n;i++)aa[i]=read();
	vis[1]=vis[n]=1;
	for(re int i=2;i<n;i++)
	{
		if(aa[i]>=aa[i-1]&&aa[i]>=aa[i+1])vis[i]=1;
		if(aa[i]<=aa[i-1]&&aa[i]<=aa[i+1])vis[i]=1;
	}
	for(re int i=1;i<=n;i++)if(vis[i])a[++len]=aa[i];
	for(re int i=2;i<=len;i++)f[i]=max(f[i-1],f[i-2]+abs(a[i]-a[i-1]));
	printf("%lld",f[len]);
	return 0;
}
原文地址:https://www.cnblogs.com/jkzcr01-QAQ/p/13574123.html