1. 程式人生 > >[BZOJ1047][HAOI2007]理想的正方形

[BZOJ1047][HAOI2007]理想的正方形

ref ble ans mit 組成 i++ ace splay zoj

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3481 Solved: 1917 [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 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 int a,b,n;
 9 int s[1001
][1001]; 10 int maxi[1001][1001]; 11 int mini[1001][1001]; 12 int q[1001],w[1001],q1[1001],w1[1001]; 13 int main() 14 { 15 scanf("%d%d%d",&a,&b,&n); 16 for(int i=1;i<=a;i++) 17 for(int j=1;j<=b;j++)scanf("%d",&s[i][j]); 18 int head=0,tail=0,head1=0,tail1=0; 19 for(int i=1;i<=a;i++)
20 { 21 head=1,tail=0; 22 head1=1,tail1=0; 23 for(int j=1;j<=b;j++) 24 { 25 while(tail>=head&&s[i][j]>=q[tail]) tail--; 26 q[++tail]=s[i][j];w[tail]=j; 27 while(tail>=head&&w[head]<j-n+1) head++; 28 maxi[i][j]=q[head]; 29 while(tail1>=head1&&s[i][j]<=q1[tail1]) tail1--; 30 q1[++tail1]=s[i][j];w1[tail1]=j; 31 while(tail1>=head1&&w1[head1]<j-n+1) head1++; 32 mini[i][j]=q1[head1]; 33 } 34 } 35 for(int j=1;j<=b;j++) 36 { 37 head=1,tail=0; 38 head1=1,tail1=0; 39 for(int i=1;i<=a;i++) 40 { 41 while(tail>=head&&maxi[i][j]>=q[tail]) tail--; 42 q[++tail]=maxi[i][j];w[tail]=i; 43 while(tail>=head&&w[head]<i-n+1) head++; 44 maxi[i][j]=q[head]; 45 while(tail1>=head1&&mini[i][j]<=q1[tail1]) tail1--; 46 q1[++tail1]=mini[i][j];w1[tail1]=i; 47 while(tail1>=head1&&w1[head1]<i-n+1) head1++; 48 mini[i][j]=q1[head1]; 49 } 50 } 51 int ans=2147483647; 52 for(int i=n;i<=a;i++) 53 for(int j=n;j<=b;j++) ans=min(ans,maxi[i][j]-mini[i][j]); 54 cout<<ans; 55 }
View Code

[BZOJ1047][HAOI2007]理想的正方形