暂无链接
矩阵
题目描述
Shy有一个矩阵.有些位置是空的,有些是满的。
Shy每次会把一个空的位置改成满的,求每次改完以后最大的空的正方形的边长。
输入说明
第一行三个整数 n,m,k n , m , k 表示矩阵的长和宽和操作数。
接下来 n n 行,每行个字符表示矩阵, X X 表示满的表示空的。
接下来 k k 行每行两个整数表示把位置 (x.y) ( x . y ) 改成满的。
输出说明
输出 k k 个整数表示每次改完以后最大的空的正方形的边长。
样例输入
7 8 4
…….
X….X.
…….
…….
.X…..
…….
…….
1 5
6 4
3 5
4 6
样例输出
5
4
4
3
数据规模
对于的数据,
1≤n,m,k≤10
1
≤
n
,
m
,
k
≤
10
;
对于
100%
100
%
的数据,
1≤n,m,k≤2000,1≤x≤n,1≤y≤m
1
≤
n
,
m
,
k
≤
2000
,
1
≤
x
≤
n
,
1
≤
y
≤
m
;
题解
什么垃圾玩意儿,悬线法暴力 O(nmk) O ( n m k ) 居然能过???不给我数据结构面子??
代码
#include<bits/stdc++.h>
#define ass min(rx-lx+1,ry-ly+1)
using namespace std;
const int M=2e3+5;
int n,m,k,sq[M][M],h[M][M],l[M][M],r[M][M],lx,ly,rx,ry;
void in()
{
char ch[M];
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i)
{
scanf("%s",ch+1);
for(int j=1;j<=m;++j)
sq[i][j]=ch[j]=='X';
}
}
void solve()
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
h[i][j]=sq[i-1][j]?1:h[i-1][j]+1,
l[i][j]=sq[i][j-1]?1:l[i][j-1]+1;
for(int j=m;j>=1;--j)
r[i][j]=sq[i][j+1]?1:r[i][j+1]+1;
}
int ans=0,tmp;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
if(sq[i][j]){h[i][j]=l[i][j]=r[i][j]=0;continue;}
if(i>1&&!sq[i-1][j])
l[i][j]=min(l[i][j],l[i-1][j]),
r[i][j]=min(r[i][j],r[i-1][j]);
tmp=min(l[i][j]+r[i][j]-1,h[i][j]);
if(ans<tmp)
{
ans=tmp;
lx=i-h[i][j]+1;ly=j-l[i][j]+1;
rx=i;ry=j+r[i][j]-1;
}
}
}
void ac()
{
int a,b;
solve();
for(int i=1;i<=k;++i)
{
scanf("%d%d",&a,&b);
sq[a][b]=1;
if(lx<=a&&a<=rx&&ly<=b&&b<=ry)solve();
printf("%d\n",ass);
}
}
int main()
{
in();ac();
return 0;
}