
思路: 实际上是用已经确定水位高度的点去更新还没有确定高度的点。一开始有坑的点的水位高度就是方块高度。每次取当前最小水位高度的点去更新其他点,就可以保证每个点只需要更新一次。
本题中边界无限高,所以不用管边界的影响(更新完就是无穷大)。假设没有边界或者边界高度为0,那么同理可以看作已经确定边界水位高度了,把边界入堆即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>using namespace std;const int maxn = 505;struct Node {int x,y,h;bool operator < (const Node&rhs) const {return h > rhs.h;}
};
int n,m;
int mxh[maxn][maxn],h[maxn][maxn];
int dirx[] = {0,0,-1,1};
int diry[] = {1,-1,0,0};priority_queue<Node>q;void bfs() {while(!q.empty()) {Node now = q.top();q.pop();int x = now.x,y = now.y,H = now.h;for(int d = 0;d < 4;d++) {int dx = x + dirx[d];int dy = y + diry[d];if(dx < 1 || dy < 1 || dx > n || dy > n) continue;if(mxh[dx][dy]) continue;mxh[dx][dy] = max(h[dx][dy],mxh[x][y]);q.push({dx,dy,mxh[dx][dy]});}}
}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 <= n;j++) {scanf("%d",&h[i][j]);mxh[i][j] = 0;}}for(int i = 1;i <= m;i++) {int x,y;scanf("%d%d",&x,&y);mxh[x][y] = h[x][y];q.push({x,y,mxh[x][y]});}bfs();for(int i = 1;i <= n;i++) {for(int j = 1;j <= n;j++) {printf("%d ",mxh[i][j] - h[i][j]);}printf("\n");}}return 0;
}