[蓝桥杯][2018年第九届真题]整理玩具(树状数组)

题目描述
小明有一套玩具,一共包含NxM个部件。这些部件摆放在一个包含NxM个小格子的玩具盒中,每个小格子中恰好摆放一个部件。

每一个部件上标记有一个0~9的整数,有可能有多个部件标记相同的整数。

小明对玩具的摆放有特殊的要求:标记相同整数的部件必须摆在一起,组成一个矩形形状。

如以下摆放是满足要求的:

00022
00033
44444

12244
12244
12233

01234
56789

以下摆放不满足要求:

11122
11122
33311

111111
122221
122221
111111

11122
11113
33333

给出一种摆放方式,请你判断是否符合小明的要求。
输入
输入包含多组数据。
第一行包含一个整数T,代表数据组数。 (1 <= T <= 10)
以下包含T组数据。
每组数据第一行包含两个整数N和M。 (1 <= N, M <= 10)
以下包含N行M列的矩阵,代表摆放方式。
输出
对于每组数据,输出YES或者NO代表是否符合小明的要求。
样例输入
3
3 5
00022
00033
44444
3 5
11122
11122
33311
2 5
01234
56789
样例输出
YES
NO
YES
思路:我以为这个题挺难的呢,因为看dotcpp上面的通过率不高。但是数据量很小,就算是暴力的话,也应该能过。我用了树状数组,但是时间复杂度还是挺高的。
我的办法是:对于x,我们分别往右往下遍历,找到这样一个矩形,判断这个矩形元素和。找元素和用树状数组节省时间。如果说这个矩形中元素都是x,就符合条件。否则就不符合。如果当前的这个元素,之前已经处理过了,就说明不符合条件。对于符合条件的,已经处理过的元素,我们将它处理成-1,以免重复处理。这一过程我用的二重循环,在这里会浪费时间,不知道有没有什么好办法。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=15;
int c[maxx][maxx];
int a[maxx][maxx];
int vis[maxx];
int n,m;

inline int lowbit(int x){return x&-x;}
inline void update(int x,int y,int v)
{
	while(x<maxx)
	{
		int ty=y;
		while(ty<maxx)
		{
			c[x][ty]+=v;
			ty+=lowbit(ty);
		}
		x+=lowbit(x);
	}
}
inline int query(int x,int y)
{
	int ans=0;
	while(x)
	{
		int ty=y;
		while(ty)
		{
			ans+=c[x][ty];
			ty-=lowbit(ty);
		}
		x-=lowbit(x);
	}
	return ans;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%1d",&a[i][j]);
		memset(c,0,sizeof(c));
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) update(i,j,a[i][j]);
		int flag=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(a[i][j]==-1) continue;
				if(vis[a[i][j]]) 
				{
					flag=0;
					break;
				}
				int x=i,y=j;
				while(a[x][j]==a[i][j]&&x<=n) x++;
				while(a[i][y]==a[i][j]&&y<=m) y++;
				x-=1;y-=1;
				int sum=query(x,y)-query(x,j-1)-query(i-1,y)+query(i-1,j-1);
				if(sum!=a[i][j]*(x-i+1)*(y-j+1)) 
				{
					flag=0;
					break;
				}
				vis[a[i][j]]=1;
				for(int kk=i;kk<=x;kk++) for(int zz=j;zz<=y;zz++) a[kk][zz]=-1;
			}
			if(!flag) break;
		}
		if(flag) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
}

ps:二维树状数组在处理这种二维矩阵的元素和上,真的挺有优势的。
努力加油a啊,(o)/~

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值