山峰

4 篇文章 0 订阅
3 篇文章 0 订阅

题意

给你 nm 的矩阵,且每个点有它的高度 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.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值