补题 F 牛客小白周赛95
讲一下 F题
最开始做这一题的时候,想到差分了,but是曼哈顿距离的差分,不太会写,,现在课后补题,这种思路其实很经典就是,将曼哈顿距离转换为切比雪夫距离。
通过学习曼哈顿距离转切比雪夫距离 我们可以知道 ,这两个距离可以互相转换。
对于曼哈顿距离中的点(x,y) 我们转换为切比雪夫坐标系下的坐标 如下
(x,y)→ (x+y,x-y)
而切比雪夫距离转换为曼哈顿距离则是 (x,y)→ (,
)
将这个旋转的图形转换为正置的图形 ,则可以使用二维差分模板了
代码如下
#include <iostream>
#include <vector>
#include <tuple>
using namespace std;
int main() {
int n, q;
cin >> n >> q;
vector<tuple<int, int, int>> arr;
for (int i = 0; i < q; ++i) {
int y, x, r;
cin >> y >> x >> r;
arr.emplace_back(y - 1, x - 1, r);
}
int nm = 2 * n + 1;
vector<vector<int>> diff(nm, vector<int>(nm, 0));
for (const auto& t : arr) {
int y = get<0>(t);
int x = get<1>(t);
int r = get<2>(t);
int dy = y + x;
int dx = y - x + n;
int a = max(0, dy - r);
int c = min(2 * n - 1, dy + r);
int b = max(0, dx - r);
int d = min(2 * n - 1, dx + r);
diff[a][b] += 1;
if (d + 1 < nm) diff[a][d + 1] -= 1;
if (c + 1 < nm) diff[c + 1][b] -= 1;
if (c + 1 < nm && d + 1 < nm) diff[c + 1][d + 1] += 1;
}
int res = 0;
for (int i = 0; i < nm; ++i) {
for (int j = 0; j < nm; ++j) {
if (i > 0) diff[i][j] += diff[i - 1][j];
if (j > 0) diff[i][j] += diff[i][j - 1];
if (i > 0 && j > 0) diff[i][j] -= diff[i - 1][j - 1];
int sy = (i + j - n) / 2;
int sx = (i - j + n) / 2;
if ((i + j - n) % 2 == 0 && 0 <= sy && sy < n && 0 <= sx && sx < n) {
if (diff[i][j] % 2 == 1) {
res += 1;
}
}
}
}
cout << res << endl;
return 0;
}
此外还有abc178的e 178e
leetcode的31023102
分别是求曼哈顿距离的最大值最小值,我们都可以转换为切比雪夫距离来算