BZOJ 1047: [HAOI2007]理想的正方形(单调队列)

来源:互联网 发布:vr医疗软件 编辑:程序博客网 时间:2024/06/14 21:08

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3510  Solved: 1933
[Submit][Status][Discuss]

Description

  有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。

Input

  第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000

Output

  仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

Sample Input

5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2

Sample Output

1

HINT

Source


题解:我们可以枚举每一个数,然后求出数到左边n个数的最小值和最大值。

可以用单调队列维护。然后再按照每一列求之前维护的最大最小值。

这样我们便能将矩阵的最优解化成一个点的最优解,共用了4次单调队列。

我们可以用数组模拟单调队列即可。

#include<set>  #include<map>     #include<stack>            #include<queue>            #include<vector>    #include<string> #include<time.h>#include<math.h>            #include<stdio.h>            #include<iostream>            #include<string.h>            #include<stdlib.h>    #include<algorithm>   #include<functional>    using namespace std;            #define ll long long      #define inf 1000000000       #define mod 1000000007             #define maxn  1005#define lowbit(x) (x&-x)            #define eps 1e-9int r,c,n,maxs[maxn][maxn],mins[maxn][maxn];int a[maxn][maxn],ans=2147483647;struct node{int x,id;};int main(void){int i,j;scanf("%d%d%d",&r,&c,&n);for(i=1;i<=r;i++)for(j=1;j<=c;j++)scanf("%d",&a[i][j]);for(i=1;i<=r;i++){node s[maxn];int st=1,ed=0;for(j=1;j<=n;j++){while(st<=ed && s[ed].x<=a[i][j])ed--;ed++;s[ed].x=a[i][j];s[ed].id=j;}maxs[i][n]=s[st].x;for(j=n+1;j<=c;j++){while(st<=ed && s[ed].x<=a[i][j])ed--;ed++;s[ed].x=a[i][j];s[ed].id=j;while(st<=ed && s[st].id<=j-n)st++;maxs[i][j]=s[st].x;}st=1;ed=0;for(j=1;j<=n;j++){while(st<=ed && s[ed].x>=a[i][j])ed--;ed++;s[ed].x=a[i][j];s[ed].id=j;}mins[i][n]=s[st].x;for(j=n+1;j<=c;j++){while(st<=ed && s[ed].x>=a[i][j])ed--;ed++;s[ed].x=a[i][j];s[ed].id=j;while(st<=ed && s[st].id<=j-n)st++;mins[i][j]=s[st].x;}}for(j=n;j<=c;j++){node q1[maxn],q2[maxn];int st1=1,ed1=0,st2=1,ed2=0;for(i=1;i<=n;i++){while(st1<=ed1 && q1[ed1].x<=maxs[i][j])ed1--;ed1++;q1[ed1].x=maxs[i][j];q1[ed1].id=i;while(st2<=ed2 && q2[ed2].x>=mins[i][j])ed2--;ed2++;q2[ed2].x=mins[i][j];q2[ed2].id=i;}if(q1[st1].x-q2[st2].x<ans)ans=q1[st1].x-q2[st2].x;for(i=n+1;i<=r;i++){while(st1<=ed1 && q1[ed1].x<=maxs[i][j])ed1--;ed1++;q1[ed1].x=maxs[i][j];q1[ed1].id=i;while(st1<=ed1 && q1[st1].id<=i-n)st1++;while(st2<=ed2 && q2[ed2].x>=mins[i][j])ed2--;ed2++;q2[ed2].x=mins[i][j];q2[ed2].id=i;while(st2<=ed2 && q2[st2].id<=i-n)st2++;if(q1[st1].x-q2[st2].x<ans)ans=q1[st1].x-q2[st2].x;}}printf("%d\n",ans);return 0;}


阅读全文
0 0
原创粉丝点击