题目链接:点击这里
题目大意:
给定一个
n
×
n
(
n
≤
250
)
n\times n(n\le 250)
n×n(n≤250) 的方阵,以及
k
(
k
≤
1
0
5
)
k(k\le 10^5)
k(k≤105) 个询问。
每次询问以
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi) 为左上角,边长为
b
b
b 的子方阵中,最大值和最小值的差
题目分析:
考虑使用二维
st
\text{st}
st 表解决此问题
设
d
p
[
i
]
[
j
]
[
k
]
[
o
]
dp[i][j][k][o]
dp[i][j][k][o] 表示以
(
i
,
j
)
(i,j)
(i,j) 为左下角的点,横纵坐标跨度分别为
2
k
,
2
o
2^k,2^o
2k,2o 这个矩形范围内的最值(下以最大值为例)
我们分四种情况来转移这个
d
p
dp
dp :
1.
k
=
0
,
o
=
0
k=0,o=0
k=0,o=0 (一个点):
d
p
[
i
]
[
j
]
[
k
]
[
o
]
=
a
[
i
]
[
j
]
dp[i][j][k][o]=a[i][j]
dp[i][j][k][o]=a[i][j]
2.
k
=
0
,
o
≠
0
k=0,o\not=0
k=0,o=0 (一列):
d
p
[
i
]
[
j
]
[
k
]
[
o
]
=
m
a
x
(
d
p
[
i
]
[
j
]
[
k
]
[
o
−
1
]
,
d
p
[
i
]
[
j
+
2
o
−
1
]
[
k
]
[
o
−
1
]
)
dp[i][j][k][o]=max(dp[i][j][k][o-1],dp[i][j+2^{o-1}][k][o-1])
dp[i][j][k][o]=max(dp[i][j][k][o−1],dp[i][j+2o−1][k][o−1])
3.
k
≠
0
,
o
=
0
k\not=0,o=0
k=0,o=0 (一行):
d
p
[
i
]
[
j
]
[
k
]
[
o
]
=
m
a
x
(
d
p
[
i
]
[
j
]
[
k
−
1
]
[
o
]
,
d
p
[
i
+
2
k
−
1
]
[
j
]
[
k
−
1
]
[
o
]
)
dp[i][j][k][o]=max(dp[i][j][k-1][o],dp[i+2^{k-1}][j][k-1][o])
dp[i][j][k][o]=max(dp[i][j][k−1][o],dp[i+2k−1][j][k−1][o])
4.
k
≠
0
,
o
≠
0
k\not=0,o\not=0
k=0,o=0 (一个矩形):
d
p
[
i
]
[
j
]
[
k
]
[
o
]
=
m
a
x
(
d
p
[
i
]
[
j
]
[
k
−
1
]
[
o
−
1
]
,
d
p
[
i
]
[
j
+
2
o
−
1
]
[
k
]
[
o
−
1
]
,
d
p
[
i
+
2
k
−
1
]
[
j
]
[
k
−
1
]
[
o
]
,
d
p
[
i
+
2
k
−
1
]
[
j
2
k
−
1
]
[
k
−
1
]
[
o
−
1
]
)
dp[i][j][k][o]=max(dp[i][j][k-1][o-1],dp[i][j+2^{o-1}][k][o-1],dp[i+2^{k-1}][j][k-1][o],dp[i+2^{k-1}][j2^{k-1}][k-1][o-1])
dp[i][j][k][o]=max(dp[i][j][k−1][o−1],dp[i][j+2o−1][k][o−1],dp[i+2k−1][j][k−1][o],dp[i+2k−1][j2k−1][k−1][o−1])
对于查询操作,我们可以把目标矩形化成
4
4
4 部分矩形(可能有交集),他们的最值就是查询答案
具体细节见代码:
// Problem: Cornfields
// Contest: Virtual Judge - POJ
// URL: https://vjudge.net/problem/POJ-2019#author=pearfish16
// Memory Limit: 30 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<unordered_map>
#define ll long long
#define inf 0x3f3f3f3f
#define Inf 0x3f3f3f3f3f3f3f3f
//#define int ll
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 250+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int n,b,k,a[maxn][maxn],maxx[maxn][maxn][10][10],minn[maxn][maxn][10][10];
void init(int n,int m)
{
for(int k = 0;(1<<k) <= n;k++)
for(int o = 0;(1<<o) <= m;o++)
for(int i = 1;i+(1<<k)-1 <= n;i++)
for(int j = 1;j+(1<<o)-1 <= m;j++)
{
if(!k && !o) maxx[i][j][k][o] = minn[i][j][k][o] = a[i][j];
if(!k && o)
{
maxx[i][j][k][o] = max(maxx[i][j][k][o-1],maxx[i][j+(1<<(o-1))][k][o-1]);
minn[i][j][k][o] = min(minn[i][j][k][o-1],minn[i][j+(1<<(o-1))][k][o-1]);
}
if(k && !o)
{
maxx[i][j][k][o] = max(maxx[i][j][k-1][o],maxx[i+(1<<(k-1))][j][k-1][o]);
minn[i][j][k][o] = min(minn[i][j][k-1][o],minn[i+(1<<(k-1))][j][k-1][0]);
}
if(k && o)
{
maxx[i][j][k][o] = max({maxx[i][j][k-1][o-1],maxx[i][j+(1<<(o-1))][k-1][o-1],maxx[i+(1<<(k-1))][j][k-1][o-1],maxx[i+(1<<(k-1))][j+(1<<(o-1))][k-1][o-1]});
minn[i][j][k][o] = min({minn[i][j][k-1][o-1],minn[i][j+(1<<(o-1))][k-1][o-1],minn[i+(1<<(k-1))][j][k-1][o-1],minn[i+(1<<(k-1))][j+(1<<(o-1))][k-1][o-1]});
}
}
}
int get_max(int x,int y,int xx,int yy)
{
int k = log2(xx-x+1),o = log2(yy-y+1);
xx = xx-(1<<k)+1; yy = yy-(1<<o)+1;
return max({maxx[x][y][k][o],maxx[xx][y][k][o],maxx[x][yy][k][o],maxx[xx][yy][k][o]});
}
int get_min(int x,int y,int xx,int yy)
{
int k = log2(xx-x+1),o = log2(yy-y+1);
xx = xx-(1<<k)+1; yy = yy-(1<<o)+1;
return min({minn[x][y][k][o],minn[xx][y][k][o],minn[x][yy][k][o],minn[xx][yy][k][o]});
}
int main()
{
n = read(),b = read(),k = read();
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++) a[i][j] = read();
init(n,n);
while(k--)
{
int x = read(),y = read();
printf("%d\n",get_max(x,y,x+b-1,y+b-1)-get_min(x,y,x+b-1,y+b-1));
}
return 0;
}