题目链接:LOJ
在讲解这道题之前,大家先要看我的另一篇博客。
看完之后,我们要开始讲题了。
思路
大家看到我的博客,大概也知道要用单调队列了,事实上,这道题用的确实是单调队列。
这道题,我们要维护两次单调队列,分别维护每一行的最大最小值和每一列的最大最小值,也就是说,第一次维护时,用某一个数组存下来,第二次维护存下来的数组,维护出一组区间最大值的区间最大值以及一组区间最小值的区间最小值,理解可以这样理解(按样例来):
1 2 5 6——这是第一次维护维护的东西
2 17 17 10 2——这是第二次维护的一二两行最大值
代码
第一部分:第一次维护行(哎呦,删Xcode的TAB真烦)
for (int j=1;j<=a;j++){
for (int i=1;i<=b;i++){
while (!maxque.empty()&&i-n+1>maxque.front())maxque.pop_front();
while (!maxque.empty()&&f[j][i]>=f[j][maxque.back()])maxque.pop_back();
maxque.push_back(i);
if (i>=n){
maxdp[j][i]=f[j][maxque.front()];
}
}
for (int i=1;i<=b;i++){
while (!minque.empty()&&i-n+1>minque.front())minque.pop_front();
while (!minque.empty()&&f[j][i]<=f[j][minque.back()])minque.pop_back();
minque.push_back(i);
if (i>=n){
mindp[j][i]=f[j][minque.front()];
}
}
maxque.clear();
minque.clear();
}
第二部分:第二次维护列
int ans=2147483647;
for (int j=n;j<=b;j++){
for (int i=1;i<=a;i++){
while (!maxque.empty()&&i-n+1>maxque.front())maxque.pop_front();
while (!minque.empty()&&i-n+1>minque.front())minque.pop_front();
while (!maxque.empty()&&maxdp[i][j]>=maxdp[maxque.back()][j])maxque.pop_back();
while (!minque.empty()&&mindp[i][j]<=mindp[minque.back()][j])minque.pop_back();
maxque.push_back(i);
minque.push_back(i);
if (i>=n){
ans=min(ans,maxdp[maxque.front()][j]-mindp[minque.front()][j]);
}
}
maxque.clear();
minque.clear();
}
整体代码:
#include<queue>
#include <iostream>
using namespace std;
int f[1005][1005];
int maxdp[1005][1005],mindp[1005][1005];
deque<int>maxque,minque;
int main() {
int n,a,b;
scanf("%d%d%d",&a,&b,&n);
for (int i=1;i<=a;i++){
for (int j=1;j<=b;j++){
scanf("%d",&f[i][j]);
}
}
for (int j=1;j<=a;j++){
for (int i=1;i<=b;i++){
while (!maxque.empty()&&i-n+1>maxque.front())maxque.pop_front();
while (!maxque.empty()&&f[j][i]>=f[j][maxque.back()])maxque.pop_back();
maxque.push_back(i);
if (i>=n){
maxdp[j][i]=f[j][maxque.front()];
}
}
for (int i=1;i<=b;i++){
while (!minque.empty()&&i-n+1>minque.front())minque.pop_front();
while (!minque.empty()&&f[j][i]<=f[j][minque.back()])minque.pop_back();
minque.push_back(i);
if (i>=n){
mindp[j][i]=f[j][minque.front()];
}
}
maxque.clear();
minque.clear();
}
int ans=2147483647;
for (int j=n;j<=b;j++){
for (int i=1;i<=a;i++){
while (!maxque.empty()&&i-n+1>maxque.front())maxque.pop_front();
while (!minque.empty()&&i-n+1>minque.front())minque.pop_front();
while (!maxque.empty()&&maxdp[i][j]>=maxdp[maxque.back()][j])maxque.pop_back();
while (!minque.empty()&&mindp[i][j]<=mindp[minque.back()][j])minque.pop_back();
maxque.push_back(i);
minque.push_back(i);
if (i>=n){
ans=min(ans,maxdp[maxque.front()][j]-mindp[minque.front()][j]);
}
}
maxque.clear();
minque.clear();
}
printf("%d\n",ans);
return 0;
}
于是,一道完整的题就做好了