bzoj1047-理想的正方形(二维单调队列)

题意: 给一个矩阵,给出行列和每个数,再给出一个N,求出所有N*N的子矩阵中最大值最小值之差的最小值
解析: 暴力枚举肯定不行,这题可以用二维单调队列做,把同一行的连续N个点缩成一个点保存最大最小值预处理
,用单调队列即可实现,再对整个矩阵进行枚举,再用一次单调队列。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
const int INF=1e9+;
const int maxn=;
int row,col,N;
int A[maxn][maxn];
int Min[maxn][maxn],Max[maxn][maxn];
int q1[maxn],q2[maxn];
int f1,f2,r1,r2;
void init() //预处理
{
for(int i=;i<=row;i++)
{
f1=,r1=;
f2=,r2=;
for(int j=;j<N;j++)
{
while(r1>=f1&&A[i][q1[r1]]>=A[i][j]) r1--;
q1[++r1]=j;
while(r2>=f2&&A[i][q2[r2]]<=A[i][j]) r2--;
q2[++r2]=j;
}
for(int j=N;j<=col;j++)
{
while(r1>=f1&&A[i][q1[r1]]>=A[i][j]) r1--;
q1[++r1]=j;
while(q1[f1]+N<=j) f1++;
Min[i][j-N+]=A[i][q1[f1]]; //缩点后的最小值 while(r2>=f2&&A[i][q2[r2]]<=A[i][j]) r2--;
q2[++r2]=j;
while(q2[f2]+N<=j) f2++;
Max[i][j-N+]=A[i][q2[f2]]; //缩点后的最大值
}
}
}
int solve()
{
int ret=INF;
for(int j=;j+N-<=col;j++) //对同一列进行枚举
{
f1=,r1=;
f2=,r2=;
int minv=INF,maxv=-INF;
for(int i=;i<N;i++)
{
while(r1>=f1&&Min[q1[r1]][j]>=Min[i][j]) r1--;
q1[++r1]=i;
while(r2>=f2&&Max[q2[r2]][j]<=Max[i][j]) r2--;
q2[++r2]=i;
}
for(int i=N;i<=row;i++)
{
while(r1>=f1&&Min[q1[r1]][j]>=Min[i][j]) r1--;
q1[++r1]=i;
while(q1[f1]+N<=i) f1++;
minv=Min[q1[f1]][j];
while(r2>=f2&&Max[q2[r2]][j]<=Max[i][j]) r2--;
q2[++r2]=i;
while(q2[f2]+N<=i) f2++;
maxv=Max[q2[f2]][j];
ret=min(ret,maxv-minv);
}
}
return ret;
}
int main()
{
scanf("%d%d%d",&row,&col,&N);
for(int i=;i<=row;i++)
for(int j=;j<=col;j++) scanf("%d",&A[i][j]);
init();
printf("%d\n",solve());
return ;
}
上一篇:Charles + Android 抓取Https数据包 (适用于Android 6.0及以下)


下一篇:[原创]使用logcat快速抓取android崩溃日志