题解:
刚睡醒写的,总是看不清括号。。。调了半天。。
就是横向一个掉队列,纵向b个单调队列,n^2的求出以(i,j)点为右下角的n*n矩形的最大值和最小值,然后n^2的统计就好~
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <algorithm> 6 7 #define N 1111 8 #define BUG system("pause") 9 10 using namespace std; 11 12 long long a,b,n; 13 long long map[N][N]; 14 long long q[N][N],h[N],t[N],s,e,dq[N]; 15 long long mx[N][N],ans,mn[N][N]; 16 17 inline void read() 18 { 19 scanf("%lld%d%d",&a,&b,&n); 20 for(long long i=1;i<=a;i++) 21 for(long long j=1;j<=b;j++) 22 scanf("%lld",&map[i][j]); 23 } 24 25 inline void getmax() 26 { 27 for(long long i=1;i<=b;i++) h[i]=1,t[i]=0; 28 for(long long i=1;i<=a;i++) 29 { 30 for(long long j=1;j<=b;j++) 31 { 32 33 while(h[j]<=t[j]&&i-q[j][h[j]]+1>n) h[j]++; 34 while(h[j]<=t[j]&&map[q[j][t[j]]][j]<=map[i][j]) t[j]--; 35 q[j][++t[j]]=i; 36 } 37 e=0; s=1; 38 for(long long j=1;j<=b;j++) 39 { 40 while(s<=e&&j-dq[s]+1>n) s++; 41 while(s<=e&&map[q[dq[e]][h[dq[e]]]][dq[e]]<=map[q[j][h[j]]][j]) e--; 42 dq[++e]=j; 43 mx[i][j]=map[q[dq[s]][h[dq[s]]]][dq[s]]; 44 } 45 } 46 } 47 48 inline void getmin() 49 { 50 for(long long i=1;i<=b;i++) h[i]=1,t[i]=0; 51 for(long long i=1;i<=a;i++) 52 { 53 for(long long j=1;j<=b;j++) 54 { 55 while(h[j]<=t[j]&&i-q[j][h[j]]+1>n) h[j]++; 56 while(h[j]<=t[j]&&map[q[j][t[j]]][j]>=map[i][j]) t[j]--; 57 q[j][++t[j]]=i; 58 } 59 e=0; s=1; 60 for(long long j=1;j<=b;j++) 61 { 62 while(s<=e&&j-dq[s]+1>n) s++; 63 while(s<=e&&map[q[dq[e]][h[dq[e]]]][dq[e]]>=map[q[j][h[j]]][j]) e--; 64 dq[++e]=j; 65 mn[i][j]=map[q[dq[s]][h[dq[s]]]][dq[s]]; 66 } 67 } 68 } 69 70 inline void go() 71 { 72 getmin(); 73 getmax(); 74 ans=1LL<<60; 75 for(long long i=n;i<=a;i++) 76 for(long long j=n;j<=b;j++) 77 ans=min(ans,mx[i][j]-mn[i][j]); 78 printf("%lld\n",ans); 79 } 80 81 int main() 82 { 83 read(),go(); 84 return 0; 85 }