题意
给你 n∗m 的矩阵,且每个点有它的高度 h[i,j] ,统计从这个点出发,在不经过小于等于 h[i,j]−p 的高度下能到无法到达比 h[i,j] 要高的地方的点的个数。
数据范围
30% n,m<=10
100% n,m<=500
分析
既然它不能到达其他的地方,即它本身就是一个连通块,且这个连通块还是一个只有大于 h[i,j]−p 的元素的连通块,还有这个连通块里的元素都是小于 h[i,j] ,即 h[i,j] 是最大的。那么我们就可以去维护一个元素都大于 h[i,j]−p 的连通块,看看这个连通块中是否 h[i,j] 为最大值即可。
具体方法
先快排所有的点,再从大到小去插入并维护连通块,每次看看这个点所在的连通块中是否他是最大的即可。维护最大值,连通块可以用并查集。
代码
var
i,j,p,ans,num,st,n,m,le:longint;
fa,ma:array[0..4000000] of longint;
bz:array[1..500,1..500] of boolean;
w:array[0..250000,1..3]of longint;
a:array[1..500,1..500] of longint;
t:array[1..4,1..2] of longint=((0,-1),(-1,0),(1,0),(0,1));
function max(l,r:longint):longint;
begin
if l<r then exit(r) else exit(l);
end;
function get(k:longint):longint;
begin
if fa[k]=0 then exit(k)
else begin
fa[k]:=get(fa[k]);
exit(fa[k]);
end;
end;
procedure qrt(l,r:longint);
var i,j,mid:longint;
begin
i:=l;j:=r;mid:=w[(l+r)shr 1,1];
repeat
while w[i,1]>mid do inc(i);
while w[j,1]<mid do dec(j);
if i<=j then begin
w[0]:=w[i];w[i]:=w[j];w[j]:=w[0];
inc(i);dec(j);
end;
until i>j;
if l<j then qrt(l,j);
if i<r then qrt(i,r);
end;
procedure pre(x,y:longint);
var l,r,i,pp,po,xgf,ygf:longint;
begin
pp:=x*1000+y;
if get(pp)=pp then ma[pp]:=a[x,y];
for i:=1 to 4 do begin
l:=x+t[i,1];r:=y+t[i,2];
if (l<1)or(r<1)or(l>n)or(r>m) then continue;
po:=l*1000+r;
if po=3001 then
l:=l;
if bz[l,r] then begin
xgf:=get(po);
ygf:=get(pp);
if xgf<>ygf then begin
fa[xgf]:=ygf;
end;
ma[ygf]:=max(ma[xgf],ma[ygf]);
end;
end;
end;
begin
readln(n,m,p);
for i:=1 to n do begin
for j:=1 to m do begin
read(a[i,j]);
inc(num);
w[num,1]:=a[i,j];w[num,2]:=i;w[num,3]:=j;
end;
readln;
end;
qrt(1,num);
st:=1;
for i:=1 to num do begin
for j:=st to num do
if (w[j,1]>w[i,1]-p)and(not bz[w[j,2],w[j,3]]) then begin
bz[w[j,2],w[j,3]]:=true;
pre(w[j,2],w[j,3]);
end else break;
st:=j;
le:=get(w[i,2]*1000+w[i,3]);
if ma[le]=w[i,1] then inc(ans);
end;
writeln(ans);
close(input);close(output);
end.