在一个的方块城市中,座标为的位置高度为,有个排水井,分别位于
在一场大雨中,每个位置的水都会往相邻的积水更低的地方流动,如果无法排出将越积越高
排水井处永远不会积水,水不会通过城市边缘排出(可以理解为城市边缘是无限高的墙)
求每个位置的积水深度
输入描述
第一行输入一个整数,代表有组测试数据 对于每一组测试数据,第一行输入个整数,接下来行每行有个整数表示第行第列的高度,接下来行每行有两个整数,表示第个排水井的位置
输出描述
对于每组测试数据,输出行,每行个整数,第行第列表示处的积水深度
数据范围
输出时每行末尾的多余空格,不影响答案正确性
样例输入
2
4 1
1 2 3 4
2 3 4 3
3 4 3 2
4 3 2 1
2 2
5 2
2 2 3 2 2
2 2 3 3 3
3 3 2 2 2
2 3 2 1 1
2 3 2 1 1
4 1
3 3
样例输出
2 1 0 0
1 0 0 1
0 0 1 2
0 1 2 3
1 1 0 1 1
1 1 0 0 0
0 0 0 0 0
0 0 0 1 1
0 0 0 1 1
样例解释
第一组样例的解释:
第二组样例的解释:
首先考虑排水口,显然排水口周围高度非递减的区域一定是干的,可以bfs将这部分的水面高度更新为的面高度,对与处于对角线的区域要单独讨论。(其实忽略也行,不过后面二分求高度会慢一点 )
然后对于没更新的区域二分水面高度,检查在当前水面高度是否高于邻近已更新区域的水面高度,最后更新水面高度。
容易想错的点是不能根据排水口的高度更新比排水口高度低的区域,因为比排水口高度低的区域的水面高度会受到多个排水口的直接或间接影响。
为了提高代码效率,排水口和未更新区域要以地面从低到高顺序搜索;用数组存储标记数组标记过的位置以便还原。
时间复杂度为。
#include<bits/stdc++.h>
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 505;
int n, m, h1[N][N], h2[N][N], T;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
bool v[N][N];
vector<pair<int, pii>> seq;
vector<pii > tmp;
inline bool check(int x, int y) {
return x >= 1 && x <= n && y >= 1 && y <= n;
}
inline void bfs1(int x, int y) {
if (h2[x][y])return;
queue<pii > q;
q.push({x, y}), h2[x][y] = h1[x][y];
while (!q.empty()) {
pii t = q.front();
q.pop();
repi(i, 0, 3) {
int nx = t.fi + dx[i], ny = t.se + dy[i];
if (!check(nx, ny) || h2[nx][ny] || h1[nx][ny] < h1[t.fi][t.se])continue;
h2[nx][ny] = h1[nx][ny], q.push({nx, ny});
}
int nx = t.fi + 1, ny = t.se + 1;
if (check(nx, ny) && h1[nx][ny] >= h1[t.fi][t.se] && !h2[nx][ny] &&
(h1[t.fi + 1][t.se] <= h1[nx][ny] || h1[t.fi][t.se + 1] <= h1[nx][ny]))
h2[nx][ny] = h1[nx][ny], q.push({nx, ny});
nx = t.fi - 1, ny = t.se + 1;
if (check(nx, ny) && h1[nx][ny] >= h1[t.fi][t.se] && !h2[nx][ny] &&
(h1[t.fi - 1][t.se] <= h1[nx][ny] || h1[t.fi][t.se + 1] <= h1[nx][ny]))
h2[nx][ny] = h1[nx][ny], q.push({nx, ny});
nx = t.fi - 1, ny = t.se - 1;
if (check(nx, ny) && h1[nx][ny] >= h1[t.fi][t.se] && !h2[nx][ny] &&
(h1[t.fi - 1][t.se] <= h1[nx][ny] || h1[t.fi][t.se - 1] <= h1[nx][ny]))
h2[nx][ny] = h1[nx][ny], q.push({nx, ny});
nx = t.fi + 1, ny = t.se - 1;
if (check(nx, ny) && h1[nx][ny] >= h1[t.fi][t.se] && !h2[nx][ny] &&
(h1[t.fi + 1][t.se] <= h1[nx][ny] || h1[t.fi][t.se - 1] <= h1[nx][ny]))
h2[nx][ny] = h1[nx][ny], q.push({nx, ny});
}
}
inline bool bfs2(int x, int y, int h) {
queue<pii > q;
tmp.clear();
q.push({x, y}), tmp.pb({x, y}), v[x][y] = true;
while (!q.empty()) {
pii t = q.front();
q.pop();
repi(i, 0, 3) {
int nx = t.fi + dx[i], ny = t.se + dy[i];
if (!check(nx, ny) || v[nx][ny] || h1[nx][ny] >= h)continue;
if (h2[nx][ny]) {
for (auto it:tmp)v[it.fi][it.se] = false;
return false;
}
if (h2[nx][ny] != h)q.push({nx, ny}), tmp.pb({nx, ny}), v[nx][ny] = true;
}
}
for (auto it:tmp)v[it.fi][it.se] = false;
return true;
}
inline void change(int x, int y, int h) {
queue<pii > q;
q.push({x, y}), h2[x][y] = h;
while (!q.empty()) {
pii t = q.front();
q.pop();
repi(i, 0, 3) {
int nx = t.fi + dx[i], ny = t.se + dy[i];
if (!check(nx, ny) || h2[nx][ny])continue;
if (h1[t.fi][t.se] <= h && h1[nx][ny] <= h) {
h2[nx][ny] = h;
if (h != h1[nx][ny])q.push({nx, ny});
} else if (h1[nx][ny] >= h2[t.fi][t.se])h2[nx][ny] = h1[nx][ny], q.push({nx, ny});
}
}
}
inline void solve(int x, int y) {
int l = h1[x][y], r = 1000;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (bfs2(x, y, mid))l = mid;
else r = mid - 1;
}
change(x, y, l);
}
int main() {
T = qr();
while (T--) {
n = qr(), m = qr();
repi(i, 1, n)repi(j, 1, n)h2[i][j] = 0, v[i][j] = false;
repi(i, 1, n) repi(j, 1, n)h1[i][j] = qr();
seq.clear();
repi(i, 1, m) {
int x = qr(), y = qr();
seq.pb({h1[x][y], {x, y}});
}
sort(seq.begin(), seq.end());
for (auto it:seq) {
int x = it.se.fi, y = it.se.se;
if (v[x][y])continue;
bfs1(x, y);
}
repi(i, 1, n)repi(j, 1, n)v[i][j] = false;
seq.clear();
repi(i, 1, n)repi(j, 1, n)if (!h2[i][j])seq.pb({h1[i][j], {i, j}});
sort(seq.begin(), seq.end());
for (auto it:seq) {
int x = it.se.fi, y = it.se.se;
if (!h2[x][y])solve(x, y);
}
repi(i, 1, n) repi(j, 1, n)printf("%d%c", h2[i][j] - h1[i][j], ce(j, n));
}
return 0;
}