SCUACM2022集训前训练-动态规划 - Virtual Judge (vjudge.net)
设 \(maxn[i][j][k]\) 为以 \((i,j)\) 为左上角,边长为 \(2^k\) 的正方形内元素的最大值
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int N = 1e3 + 10; int n, m, len, Log[N]; int maxn[N][N][15], minn[N][N][15]; int a[N][N]; void init() { for (int i = 2; i < N; i++) Log[i] = Log[i / 2] + 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) maxn[i][j][0] = minn[i][j][0] = a[i][j]; for (int k = 1; k <= 12; k++) { for (int i = 1; i + (1 << k) - 1 <= n; i++) { for (int j = 1; j + (1 << k) - 1 <= m; j++) { int t1, t2, t3, t4; t1 = maxn[i][j][k-1]; t2 = maxn[i + (1 << k - 1)][j][k-1]; t3 = maxn[i][j + (1 << k - 1)][k-1]; t4 = maxn[i + (1 << k - 1)][j + (1 << k - 1)][k-1]; maxn[i][j][k] = max({t1, t2, t3, t4}); t1 = minn[i][j][k-1]; t2 = minn[i + (1 << k - 1)][j][k-1]; t3 = minn[i][j + (1 << k - 1)][k-1]; t4 = minn[i + (1 << k - 1)][j + (1 << k - 1)][k-1]; minn[i][j][k] = min({t1, t2, t3, t4}); } } } } int query(int sx, int sy, int len) { int k = Log[len]; int ex = sx + len - 1, ey = sy + len - 1; int t1, t2, t3, t4; t1 = maxn[sx][sy][k]; t2 = maxn[sx][ey + 1 - (1 << k)][k]; t3 = maxn[ex + 1 - (1 << k)][sy][k]; t4 = maxn[ex + 1 - (1 << k)][ey + 1 - (1 << k)][k]; int mx = max({t1, t2, t3, t4}); t1 = minn[sx][sy][k]; t2 = minn[sx][ey + 1 - (1 << k)][k]; t3 = minn[ex + 1 - (1 << k)][sy][k]; t4 = minn[ex + 1 - (1 << k)][ey + 1 - (1 << k)][k]; int mn = min({t1, t2, t3, t4}); // cout << sx << " " << sy << ": " << mx << " " << mn << endl; return mx - mn; } int main() { scanf("%d%d%d", &n, &m, &len); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]); init(); int ans = 2e9; for (int sx = 1; sx + len - 1 <= n; sx++) for (int sy = 1; sy + len - 1 <= m; sy++) ans = min(ans, query(sx, sy, len)); printf("%d\n", ans); return 0; }