横着用单调队列求最值,再竖着做单调队列即可
1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(int i=l;i<=r;i++) 3 #define dec(i,l,r) for(int i=l;i>=r;i--) 4 #define link(x) for(edge *j=h[x];j;j=j->next) 5 #define mem(a) memset(a,0,sizeof(a)) 6 #define inf 1e9 7 #define ll long long 8 #define succ(x) (1<<x) 9 #define NM 1000+5 10 using namespace std; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 14 while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 15 return x*f; 16 } 17 int n,m,p,a[NM][NM],b[NM][NM],c[NM][NM],qt,qh,q[NM],_q[NM],_qh,_qt,s; 18 int main(){ 19 // freopen("data.in","r",stdin); 20 n=read();m=read();p=read(); 21 inc(i,1,n) 22 inc(j,1,m)a[i][j]=read(); 23 inc(i,1,n){ 24 qh=1;qt=0;mem(q); 25 inc(j,1,p){ 26 while(qh<=qt&&a[i][q[qt]]<=a[i][j])qt--; 27 q[++qt]=j; 28 } 29 b[i][p]=a[i][q[qh]]; 30 inc(j,p+1,m){ 31 while(qh<=qt&&q[qh]<j-p+1)qh++; 32 while(qh<=qt&&a[i][q[qt]]<=a[i][j])qt--; 33 q[++qt]=j; 34 b[i][j]=a[i][q[qh]]; 35 } 36 qh=1;qt=0;mem(q); 37 inc(j,1,p){ 38 while(qh<=qt&&a[i][q[qt]]>=a[i][j])qt--; 39 q[++qt]=j; 40 } 41 c[i][p]=a[i][q[qh]]; 42 inc(j,p+1,m){ 43 while(qh<=qt&&q[qh]<j-p+1)qh++; 44 while(qh<=qt&&a[i][q[qt]]>=a[i][j])qt--; 45 q[++qt]=j; 46 c[i][j]=a[i][q[qh]]; 47 } 48 } 49 /* inc(j,1,m)printf("%d ",b[i][j]);printf("\n");} 50 inc(i,1,n){ 51 inc(j,1,m)printf("%d ",c[i][j]);printf("\n");}*/ 52 s=inf; 53 inc(j,p,m){ 54 _qh=qh=1;_qt=qt=0;mem(q);mem(_q); 55 inc(i,1,p){ 56 while(qh<=qt&&b[q[qt]][j]<=b[i][j])qt--; 57 q[++qt]=i; 58 while(_qh<=_qt&&c[_q[_qt]][j]>=c[i][j])_qt--; 59 _q[++_qt]=i; 60 } 61 s=min(s,b[q[qh]][j]-c[_q[_qh]][j]); 62 // printf("%d ",s); 63 inc(i,p+1,n){ 64 while(qh<=qt&&q[qh]<i-p+1)qh++; 65 while(qh<=qt&&b[q[qt]][j]<=b[i][j])qt--; 66 q[++qt]=i; 67 while(_qh<=_qt&&_q[_qh]<i-p+1)_qh++; 68 while(_qh<=_qt&&c[_q[_qt]][j]>=c[i][j])_qt--; 69 _q[++_qt]=i;s=min(s,b[q[qh]][j]-c[_q[_qh]][j]); 70 // printf("%d ",b[q[qh]][j]-c[_q[_qh]][j]); 71 } 72 // printf("\n"); 73 } 74 printf("%d\n",s); 75 return 0; 76 }