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 }