赛时想到了一个比较简单的方法,成功通过。
如果在每次询问时直接枚举整个矩阵,显然会超时,因此需要优化。
枚举一维坐标
由于每次只需要枚举与 (x, y) 曼哈顿距离为 k 的点,不需要枚举所有点,因此可以枚举 x':
- 对应的
y'有两个:
y1' = y + (k - |x' - x|)
y2' = y - (k - |x' - x|)此时单次查询的复杂度为,总复杂度
。
已知,
,仍然超时。
同理,枚举y'也会得到,同样不可行。
枚举较小维度
考虑枚举 和
中的较小值,复杂度为
。
表面上看仍然很大,但题目限制 ,因此:
于是复杂度上界为:
这个复杂度在极限情况下比较临界,赛时耗时约 2000ms 通过。
参考代码
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
void solve() {
int n, m, q;
cin >> n >> m >> q;
vector<vector<int>> h(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> h[i][j];
while (q--) {
int x, y, k;
cin >> x >> y >> k;
vector<int> res;
if (n > m) {
// 枚举列
for (int j = 1; j <= m; j++) {
int dy = abs(j - y);
int dx = k - dy;
if (dx >= 0) {
int x1 = x + dx;
if (x1 >= 1 && x1 <= n) res.push_back(h[x1][j]);
x1 = x - dx;
if (x1 >= 1 && x1 <= n) res.push_back(h[x1][j]);
}
}
} else {
// 枚举行
for (int i = 1; i <= n; i++) {
int dx = abs(i - x);
int dy = k - dx;
if (dy >= 0) {
int y1 = y + dy;
if (y1 >= 1 && y1 <= m) res.push_back(h[i][y1]);
y1 = y - dy;
if (y1 >= 1 && y1 <= m) res.push_back(h[i][y1]);
}
}
}
if (res.empty()) {
cout << -1 << '\n';
} else {
int ans = -INF;
for (int t : res) ans = max(ans, t);
cout << ans << '\n';
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) solve();
return 0;
}

京公网安备 11010502036488号