BZOJ 1047 理想的正方形(单调队列)
刚开始用二维RMQ直接给超内存了。。。
用单调队列可以做到O(n^2)的复杂度。具体是先把每行用单调队列处理一下。再把处理后的用列单调队列处理下。
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-9 # define MOD 12345678 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int res=0, flag=0; char ch; if((ch=getchar())=='-') flag=1; else if(ch>='0'&&ch<='9') res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+(ch-'0'); return flag?-res:res; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=1005; //Code begin... int val[N][N], row_max[N][N], row_min[N][N], col_max[N][N], col_min[N][N], que[N], head, tail; int main () { int n, m, a; scanf("%d%d%d",&n,&m,&a); FOR(i,1,n) FOR(j,1,m) scanf("%d",&val[i][j]); FOR(i,1,n) { head=-1; tail=0; FOR(j,1,m) { while (head>=tail&&val[i][j]>=val[i][que[head]]) --head; que[++head]=j; if (que[head]-que[tail]>=a) ++tail; if (j>=a) row_max[i][j-a+1]=val[i][que[tail]]; } head=-1; tail=0; FOR(j,1,m) { while (head>=tail&&val[i][j]<=val[i][que[head]]) --head; que[++head]=j; if (que[head]-que[tail]>=a) ++tail; if (j>=a) row_min[i][j-a+1]=val[i][que[tail]]; } } FOR(j,1,m-a+1) { head=-1; tail=0; FOR(i,1,n) { while (head>=tail&&row_max[i][j]>=row_max[que[head]][j]) --head; que[++head]=i; if (que[head]-que[tail]>=a) ++tail; if (i>=a) col_max[i-a+1][j]=row_max[que[tail]][j]; } head=-1; tail=0; FOR(i,1,n) { while (head>=tail&&row_min[i][j]<=row_min[que[head]][j]) --head; que[++head]=i; if (que[head]-que[tail]>=a) ++tail; if (i>=a) col_min[i-a+1][j]=row_min[que[tail]][j]; } } int ans=INF; FOR(i,1,n-a+1) FOR(j,1,m-a+1) ans=min(ans,col_max[i][j]-col_min[i][j]); printf("%d\n",ans); return 0; }