题目描述
小明有一套玩具,一共包含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)/~