链接
https://vjudge.net/problem/UVA-12130
题解
写这种题的时候思路一定要清晰,因为一点点小错可能就是致命的
把所有的点按照高度递减排序,逐个加入,用并查集维护连通性
只要判断一下当前点所在点集的最大值是否等于这个点的值即可知道这个点是不是summit
代码
#include <bits/stdc++.h>
#define maxn 510
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
ll code[maxn][maxn], h, w, d, tot, height[maxn][maxn];
bool mark[maxn][maxn];
struct position
{
ll x, y, height;
}pos[maxn*maxn];
bool operator<(position p1, position p2)
{
return p1.height > p2.height;
}
class UF
{
public:
ll f[maxn*maxn], mx[maxn*maxn];
void init(ll n)
{
for(auto i=1;i<=n;i++)f[i]=i;
}
ll find(ll x){return x==f[x]?x:f[x]=find(f[x]);}
void merge(ll x, ll y)
{
auto fx(find(x)), fy(find(y));
mx[fy]=max(mx[fy],mx[fx]);
f[fx]=fy;
}
ll qmax(ll x)
{
return mx[find(x)];
}
}uf;
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
void init()
{
ll i, j;
h=read(), w=read(), d=read();
tot=0;
for(i=1;i<=h;i++)for(j=1;j<=w;j++)
{
tot++;
pos[tot].x=i, pos[tot].y=j, pos[tot].height=read();
uf.mx[tot]=pos[tot].height;
height[i][j]=pos[tot].height;
code[i][j]=tot;
}
sort(pos+1,pos+tot+1);
}
bool ok(ll x, ll y)
{
return x>=1 and x<=h and y>=1 and y<=w;
}
void solve()
{
ll i, dx[]{1,0,-1,0}, dy[]{0,1,0,-1}, dir, p, ans(0ll);
uf.init(tot);
for(p=i=1;i<=tot;i++)
{
while(p<=tot and pos[p].height>pos[i].height-d)
{
auto x=pos[p].x, y=pos[p].y;
for(dir=0;dir<4;dir++)
{
if(ok(x+dx[dir],y+dy[dir]) and height[x+dx[dir]][y+dy[dir]]>pos[i].height-d)
{
uf.merge(code[x][y],code[x+dx[dir]][y+dy[dir]]);
}
}
p++;
}
if(pos[i].height==uf.qmax(code[pos[i].x][pos[i].y]))ans++;
}
printf("%lld\n",ans);
}
int main()
{
auto T=read();
while(T--)
{
init();
solve();
}
return 0;
}