BZOJ 1047 [HAOI2007]理想的正方形【单调队列

来源:互联网 发布:杭州淘宝城附近楼盘 编辑:程序博客网 时间:2024/06/10 22:38

显然就是扫一下所有n*n的矩阵的最大值和最小值只差取min,单调队列横着扫一遍竖着扫一遍就好了


好好取名字,少用ctrl+C ctrl+V【因为这个我调了一年233333

#include<bits/stdc++.h>#define MAXN 1006using namespace std;int n,m,k;inline int read(){register char ch = getchar();while(!isdigit(ch))ch = getchar();register int rtn = 0;while(isdigit(ch))rtn = rtn*10 + ch - '0' , ch = getchar();return rtn;}int g[MAXN][MAXN];int f[MAXN][MAXN],h[MAXN][MAXN];int que[MAXN],head,tail;int q2[MAXN],head2,tail2;int main(){//freopen("1.in","r",stdin);n = read() , m = read() , k = read();for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)g[i][j] = read();for(int j=1;j<=n;++j){memset(que,0,sizeof que);memset(q2,0,sizeof q2);head = tail = 0;head2 = tail2 = 0;for(int i=1;i<k;++i){while(tail>head && g[j][i]>g[j][que[tail-1]])--tail;que[tail++] = i;while(tail2>head2 && g[j][i]<g[j][q2[tail2-1]])--tail2;q2[tail2++] = i;}for(int i=k;i<=m;++i){while(tail>head && g[j][i]>g[j][que[tail-1]])--tail;que[tail++] = i;while(tail>head && que[head]+k<=i)++head;f[j][i] = g[j][que[head]];while(tail2>head2 && g[j][i]<g[j][q2[tail2-1]])--tail2;q2[tail2++] = i;while(tail2>head2 && q2[head2]+k<=i)++head2;h[j][i] = g[j][q2[head2]];}}int ans = 0x3f3f3f3f;for(int j=k;j<=m;++j){memset(que,0,sizeof que);memset(q2,0,sizeof q2);head = tail = head2 = tail2 = 0;for(int i=1;i<k;++i){while(tail>head && f[i][j] > f[que[tail-1]][j])--tail;que[tail++] = i;while(tail2>head2 && h[i][j] < h[q2[tail2-1]][j])--tail2;q2[tail2++] = i;}for(int i=k;i<=n;++i){while(tail>head && f[i][j]>f[que[tail-1]][j])--tail;que[tail++] = i;while(tail>head && que[head]+k<=i)++head;while(tail2>head2 && h[i][j]<h[q2[tail2-1]][j])--tail2;q2[tail2++] = i;while(tail2>head2 && q2[head2]+k<=i)++head2;ans = min(ans,f[que[head]][j]-h[q2[head2]][j]);}}printf("%d",ans);return 0;}


0 0