haoi2007 理想的正方形
链接:https://www.luogu.org/problemnew/show/P2216
题解:维护两次单调队列
代码:
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #define ll long long using namespace std; ll a,b,n,h,h3,t3,h4,t4,f[1022][1022],p1[1022][1022],p2[1022][1022]; ll f1[1022][1022],f2[1022][1022],f3[1022],f4[1022]; ll id1[1022][1022],id2[1022][1022],id3[1022],id4[1022]; ll head1[1022],head2[1022],tail1[1022],tail2[1022]; void insert1(ll x,ll y,ll z) { ll i; for (i=tail1[x];i>=head1[x];i--) { if (f1[x][i]>z) break; } f1[x][++i]=z; tail1[x]=i; id1[x][i]=y; } void insert2(ll x,ll y,ll z) { ll i; for (i=tail2[x];i>=head2[x];i--) { if (f2[x][i]<z) break; } f2[x][++i]=z; tail2[x]=i; id2[x][i]=y; } void insert3(ll x,ll y) { ll i; for (i=t3;i>=h3;i--) { if (f3[i]>y) break; } f3[++i]=y; t3=i; id3[i]=x; } void insert4(ll x,ll y) { ll i; for (i=t4;i>=h4;i--) { if (f4[i]<y) break; } f4[++i]=y; t4=i; id4[i]=x; } void clear(ll a[1022]) { for(ll i=0;i<=1021;i++) a[i]=1; } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); ios::sync_with_stdio(false); ll ans=999999999; memset(f1,-1,sizeof(f1)); memset(f2,-1,sizeof(f2)); clear(head1); clear(head2); cin>>a>>b>>n; for (ll i=1;i<=a;i++) for (ll j=1;j<=b;j++) { cin>>f[i][j]; } for (ll j=1;j<=b;j++) for (ll i=1;i<=n-1;i++) { if (i>=id1[j][head1[j]]+n) head1[j]++; insert1(j,i,f[i][j]); if (i>=id2[j][head2[j]]+n) head2[j]++; insert2(j,i,f[i][j]); } for (ll i=1;i<=a-n+1;i++) { for (ll j=1;j<=b;j++) { ll ii=i+n-1; if (ii>=id1[j][head1[j]]+n) head1[j]++; insert1(j,ii,f[ii][j]); if (ii>=id2[j][head2[j]]+n) head2[j]++; insert2(j,ii,f[ii][j]); } memset(f3,-1,sizeof(f3)); memset(f4,-1,sizeof(f4)); h3=1;t3=0;h4=1;t4=0; for (ll j=1;j<=n-1;j++) { insert3(j,f1[j][head1[j]]); insert4(j,f2[j][head2[j]]); } for (ll j=n;j<=b;j++) { if (j>=id3[h3]+n) h3++; insert3(j,f1[j][head1[j]]); if (j>=id4[h4]+n) h4++; insert4(j,f2[j][head2[j]]); ans=min(ans,f3[h3]-f4[h4]); } } cout<<ans; }