1. 程式人生 > >luogu 2216 理想的正方形 單調隊列(其實沒有DP)

luogu 2216 理想的正方形 單調隊列(其實沒有DP)

clas using const isdigit max turn gist getchar style

#include<bits/stdc++.h>

using namespace std;

const int A=1050;
const int N=105;
int a,b,n;
int g[A][A],q[A][N],Q[A][N];
int head[A],tail[A];
int Head[A],Tail[A];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==-)f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1
)+(x<<3)+(ch^48);ch=getchar();} return x*f;} int main(){ a=read(),b=read(),n=read(); for(register int i=1;i<=a;i++) for(register int j=1;j<=b;j++) g[i][j]=read(); for(register int j=1;j<=b;j++){ head[j]=tail[j]=1; Head[j]=Tail[j]=1; for(register int
i=1;i<=n-1;i++){ while(head[j]<=tail[j]&&g[i][j]<=g[q[j][tail[j]]][j]) tail[j]--; q[j][++tail[j]]=i; while(Head[j]<=Tail[j]&&g[i][j]>=g[Q[j][Tail[j]]][j]) Tail[j]--; Q[j][++Tail[j]]=i; } } int ans=0x3f3f3f3f;
for(register int i=n;i<=a;i++){ for(register int j=1;j<=b;j++){ while(head[j]<=tail[j]&&q[j][head[j]]<i-n+1) head[j]++; while(head[j]<=tail[j]&&g[i][j]<=g[q[j][tail[j]]][j]) tail[j]--; q[j][++tail[j]]=i; while(Head[j]<=Tail[j]&&Q[j][Head[j]]<i-n+1) Head[j]++; while(Head[j]<=Tail[j]&&g[i][j]>=g[Q[j][Tail[j]]][j]) Tail[j]--; Q[j][++Tail[j]]=i; } for(register int j=n;j<=b;j++){ int mi=0x3f3f3f3f,mx=-0x3f3f3f3f; for(register int k=j-n+1;k<=j;k++){ mi=min(mi,g[q[k][head[k]]][k]); mx=max(mx,g[Q[k][Head[k]]][k]); } ans=min(ans,mx-mi); } } printf("%d\n",ans);return 0; }

二維單調隊列

luogu 2216 理想的正方形 單調隊列(其實沒有DP)