二维RMQ。求一个矩阵的子矩阵各元素的最大值与最小值之差。用int会超内存,改用short。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 255;
int n, b, k;
short dpmin[maxn][maxn][10][10];
short dpmax[maxn][maxn][10][10];
short val[maxn][maxn];
void init()
{
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
dpmin[i][j][0][0] = dpmax[i][j][0][0] = val[i][j];
int k = (int)(log((double)n) / log(2.0));
for (int i = 0; i <= k; ++i)
{
for (int j = 0; j <= k; ++j)
{
if (0 == i && 0 == j)
continue;
for (int r = 1; r + (1 << i) - 1 <= n; ++r)
{
for (int c = 1; c + (1 << j) - 1 <= n; ++c)
{
if (0 == i)
{
dpmin[r][c][i][j] = min(dpmin[r][c][i][j-1], dpmin[r][c+(1<<(j-1))][i][j-1]);
dpmax[r][c][i][j] = max(dpmax[r][c][i][j-1], dpmax[r][c+(1<<(j-1))][i][j-1]);
}
else
{
dpmin[r][c][i][j] = min(dpmin[r][c][i-1][j], dpmin[r+(1<<(i-1))][c][i-1][j]);
dpmax[r][c][i][j] = max(dpmax[r][c][i-1][j], dpmax[r+(1<<(i-1))][c][i-1][j]);
}
}
}
}
}
}
short query(int r1, int c1, int r2, int c2)
{
int kr = (int)(log((double)r2 - r1 + 1) / log(2.0));
int kc = (int)(log((double)c2 - c1 + 1) / log(2.0));
short t1 = dpmax[r1][c1][kr][kc];
short t2 = dpmax[r2-(1<<kr)+1][c1][kr][kc];
short t3 = dpmax[r1][c2-(1<<kc)+1][kr][kc];
short t4 = dpmax[r2-(1<<kr)+1][c2-(1<<kc)+1][kr][kc];
short m1 = dpmin[r1][c1][kr][kc];
short m2 = dpmin[r2-(1<<kr)+1][c1][kr][kc];
short m3 = dpmin[r1][c2-(1<<kc)+1][kr][kc];
short m4 = dpmin[r2-(1<<kr)+1][c2-(1<<kc)+1][kr][kc];
return max(max(t1, t2), max(t3, t4)) - min(min(m1, m2), min(m3, m4));
}
void read()
{
scanf("%d %d %d", &n, &b, &k);
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
scanf("%d", &val[i][j]);
}
init();
int r1, c1, r2, c2;
for (int i = 0; i < k; ++i)
{
scanf("%d %d", &r1, &c1);
r2 = r1 + b - 1;
c2 = c1 + b - 1;
printf("%d\n", query(r1, c1, r2, c2));
}
}
int main()
{
read();
return 0;
}