Files
contests/2023/rcpc/d2/editorial/b-the-floor-is-lava-46.cpp
2024-04-22 16:45:09 +03:00

162 lines
3.4 KiB
C++

#include <bits/stdc++.h>
#warning That's the baby, that's not my baby
typedef long long ll;
using namespace std;
/**
Solutie:
Rotim la 45, acum ne fixam unul dintre cele K puncte.
Observam ca va face cel mult n + m - 1 (< 2 * max(n, m)) pasi =>
ne vom uita pentru r pasi, care este intaltimea maxima la care putem ajunge.
Practic avem un query de maxim pe un patrat din matrice => putem face rmq
Complexitate temporala: O(N^2 * logN + K * N)
**/
const int NMAX = 750;
int a[NMAX + 1][NMAX + 1];
int b[2 * NMAX + 2][2 * NMAX + 2];
int rmqLine[12][2 * NMAX + 1][2 * NMAX + 1];
int rmqCol[12][2 * NMAX + 1][2 * NMAX + 1];
int lg2[2 * NMAX + 1];
int N;
const int p2[14] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192};
int queryLine (int x, int l, int r) {
l = max(l, 1);
r = min(r, N);
int k = lg2[r - l + 1];
return max(rmqLine[k][x][l], rmqLine[k][x][r - p2[k] + 1]);
}
int queryCol (int x, int l, int r) {
l = max(l, 1);
r = min(r, N);
int k = lg2[r - l + 1];
return max(rmqCol[k][x][l], rmqCol[k][x][r - p2[k] + 1]);
}
int answer[NMAX * NMAX + 1];
int mini[2 * NMAX + 1];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
int n, m, k;
cin >> n >> m >> k;
N = max(n, m);
int maxel = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
b[i + j - 1][i - j + N] = a[i][j];
maxel = std::max(maxel, a[i][j]);
}
}
N <<= 1;
for (int i = 2; i <= N; i++) {
lg2[i] = lg2[i >> 1] + 1;
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (!b[i][j]) {
rmqLine[0][i][j] = rmqCol[0][j][i] = 1e9;
}
rmqLine[0][i][j] = rmqCol[0][j][i] = b[i][j];
// cout << setw(3) << b[i][j];
}
// cout << '\n';
}
for (int k = 1; p2[k] <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j + p2[k] - 1 <= N; j++) {
rmqLine[k][i][j] = max(rmqLine[k - 1][i][j], rmqLine[k - 1][i][j + p2[k - 1]]);
}
}
for (int j = 1; j <= N; j++) {
for (int i = 1; i + p2[k] - 1 <= N; i++) {
rmqCol[k][j][i] = max(rmqCol[k - 1][j][i], rmqCol[k - 1][j][i + p2[k - 1]]);
}
}
}
for (int r = 1; r <= N; r++) {
mini[r] = 1e9;
}
while (k--) {
int x, y;
cin >> x >> y;
int i = x + y - 1;
int j = x - y + N / 2;
// cout << " ? " << b[i][j] << " - " << a[x][y] << '\n';
int cur = 0;
for (int r = 1; r <= N; r++) {
int x1 = i - r + 1, y1 = j - r + 1, x2 = i + r - 1, y2 = j + r - 1;
if (x1 > 0) {
cur = max(cur, queryLine(x1, y1, y2));
}
if (x2 <= N) {
cur = max(cur, queryLine(x2, y1, y2));
}
if (y1 > 0) {
cur = max(cur, queryCol(y1, x1, x2));
}
if (y2 <= N) {
cur = max(cur, queryCol(y2, x1, x2));
}
mini[r] = min(mini[r], cur);
}
}
for (int r = 1; r <= N; r++) {
// cout << " > " << mini[r] << '\n';
if (mini[r] <= n * m) {
answer[mini[r] + 1] = max(answer[mini[r] + 1], r);
}
}
for (int i = 1; i <= n * m; i++) {
answer[i] = max(answer[i], answer[i - 1]);
if (i > maxel) {
std::cout << "-1 ";
} else {
cout << answer[i] << ' ';
}
}
return 0;
}
/**
6 5 6
30 14 11 22 16
7 5 6 3 23
20 1 5 2 17
21 1 4 2 6
17 7 3 24 3
26 25 13 14 10
2 2
3 2
4 4
5 5
2 4
4 3
**/