#P2875. USACO(129)动态规划(单调队列优化)2:玉米实验[Cornfields, 2003 Mar]
USACO(129)动态规划(单调队列优化)2:玉米实验[Cornfields, 2003 Mar]
Description
【题意】约翰所有的土地被分成 $N \times N$ 块,其中第 $r$ 行第 $c$ 列的玉米质量为 $A_{r,c}$。
经过前期考察,他已经锁定了 $K$ 片区域作为实验基地的候选,其中第 $i$ 片区域是从 $R_i$ 行 $C_i$ 列开始,到 $R_i + B - 1$ 行 $C_i + B - 1$ 列结束的一个 $B \times B$ 的区域。
请帮助约翰计算一下,在这些候选区域里,玉米的最高质量与最低质量之差分别是多少。
【输入格式】
• 第一行三个整数 $N , B , K$($1 \le B \le N \le 250,1 \le K \le 10^5$)。
• 下来 $N \times N$ 的矩阵$A_{i,j}$( $0 \le A_{i,j} \le 250$)。
• 下来 $K$ 行,每行两个整数 $R_i$ 和 $C_i$($1 \le R_i, C_i \le N$)。【输出格式】
• 总共 $K$ 行。第 $i$ 行表示第 $i$ 片候选区域中最高质量与最低质量之差。
【样例输入】
5 3 1
5 1 2 6 3
1 3 5 2 7
7 2 4 6 1
9 9 8 6 5
0 6 9 3 9
1 2
【样例输出】
5
【解释】
最高为 6,最低为 1,所以差是 5
Hint
by hansang:#include<bits/stdc++.h>
using namespace std;
const int N=260;
int q1[N], q2[N], a[N][N], f1[N][N], f2[N][N]; //1small,2big
int main(){
int n, m, K; scanf("%d%d%d", &n, &m, &K);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) scanf("%d", &a[i][j]);
memset(f1, 0x3f, sizeof(f1));
memset(f2, 0, sizeof(f2));
for(int i=1; i<=n; i++){
int l1=1, r1=0, l2=1, r2=0;
for(int j=1; j<=n; j++){
int t=max(1, j-m+1);
while(l1<=r1 && q1[l1]<=j-m) l1++;
while(l1<=r1 && a[i][q1[r1]]>=a[i][j]) r1--;
q1[++r1]=j; f1[i][t]=min(f1[i][t], a[i][q1[l1]]);
while(l2<=r2 && q2[l2]<=j-m) l2++;
while(l2<=r2 && a[i][q2[r2]]<=a[i][j]) r2--;
q2[++r2]=j; f2[i][t]=max(f2[i][t], a[i][q2[l2]]);
}
}
for(int i=1; i<=K; i++){
int l, r; scanf("%d%d", &l, &r);
int s1=N, s2=0;
for(int j=l; j<=l+m-1; j++){
s1=min(s1, f1[j][r]);
s2=max(s2, f2[j][r]);
}
printf("%d\n", s2-s1);
}
return 0;
}
</p>