bzoj 1047[HAOI2007]理想的正方形

题目大意:在一个矩阵中找一个n*n的正方形,使得正方形中最大值与最小值得差最小。

这道题就是使用单调队列去解决

使用单调队列去求出每个数字在以它为右下角的矩形中数的最值,然后找出在矩阵中最小的那个正方形。

居然因为ans的值赋的太小找了将近20分钟。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1005
 4 int c[N][N],vis[N],pos[N];
 5 int mx[N][N],mn[N][N],tot1[N],tot2[N];
 6 int a,b,n;
 7 int main(){
 8     scanf("%d%d%d",&a,&b,&n);
 9     for(int i=1;i<=a;i++)
10         for(int j=1;j<=b;j++)
11             scanf("%d",&c[i][j]);
12     for(int i=1;i<=a;i++){
13         int l=1,r=1;
14         for(int j=1;j<=b;j++){
15             while(l<r&&vis[r-1]<=c[i][j])r--;
16             vis[r]=c[i][j];pos[r]=j;r++;
17             if(pos[l]==j-n)l++;
18             if(j>=n)mx[i][j]=vis[l];
19         }
20         l=1,r=1;
21         for(int j=1;j<=b;j++){
22             while(l<r&&vis[r-1]>=c[i][j])r--;
23             vis[r]=c[i][j];pos[r]=j;r++;
24             if(pos[l]==j-n)l++;
25             if(j>=n)mn[i][j]=vis[l];
26         }
27     }
28     int ans=200000000;//这个要赋一个很大的值,不然会wa掉 
29     for(int i=n;i<=b;i++){
30         int l=1,r=1;
31         for(int j=1;j<=a;j++){
32             while(l<r&&vis[r-1]>=mn[j][i])r--;
33             vis[r]=mn[j][i];pos[r]=j;r++;
34             if(pos[l]==j-n)l++;
35             if(j>=n)tot1[j]=vis[l];
36         }
37         l=1,r=1;
38         for(int j=1;j<=a;j++){
39             while(l<r&&vis[r-1]<=mx[j][i])r--;
40             vis[r]=mx[j][i];pos[r]=j;r++;
41             if(pos[l]==j-n)l++;
42             if(j>=n)tot2[j]=vis[l];
43         }
44         for(int i=n;i<=a;i++)ans=min(ans,tot2[i]-tot1[i]);
45     }
46     printf("%d\n",ans);
47     return 0;
48 }    

 

posted @ 2017-09-18 21:21  Elfish?  阅读(230)  评论(1编辑  收藏  举报