bzoj千题计划215:bzoj1047: [HAOI2007]理想的正方形
http://www.lydsy.com/JudgeOnline/problem.php?id=1047
先用单调队列求出每横着n个最大值
再在里面用单调队列求出每竖着n个的最大值
这样一个位置就代表了一个n*n矩阵的最大值
同理求出最小值
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 1001 int num[N][N]; int mx1[N][N],mx2[N][N]; int mi1[N][N],mi2[N][N]; int q[N],pos[N],h,t; void read(int &x) { x=0; int f=1; char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } x*=f; } int main() { #ifndef ONLINE_JUDGE freopen("data.in","r",stdin); freopen("xxy.out","w",stdout); #endif int a,b,n; read(a); read(b); read(n); for(int i=1;i<=a;++i) for(int j=1;j<=b;++j) read(num[i][j]); for(int i=1;i<=a;++i) { h=t=0; for(int j=1;j<=b;++j) { while(h<t && j-pos[h]+1>n) h++; while(h<t && num[i][j]>q[t-1]) t--; q[t]=num[i][j]; pos[t++]=j; if(j>=n) mx1[i][j]=q[h]; } } for(int j=n;j<=b;++j) { h=t=0; for(int i=1;i<=a;++i) { while(h<t && i-pos[h]+1>n) h++; while(h<t && mx1[i][j]>q[t-1]) t--; q[t]=mx1[i][j]; pos[t++]=i; if(i>=n) mx2[i][j]=q[h]; } } for(int i=1;i<=a;++i) { h=t=0; for(int j=1;j<=b;++j) { while(h<t && j-pos[h]+1>n) h++; while(h<t && num[i][j]<q[t-1]) t--; q[t]=num[i][j]; pos[t++]=j; if(j>=n) mi1[i][j]=q[h]; } } for(int j=n;j<=b;++j) { h=t=0; for(int i=1;i<=a;++i) { while(h<t && i-pos[h]+1>n) h++; while(h<t && mi1[i][j]<q[t-1]) t--; q[t]=mi1[i][j]; pos[t++]=i; if(i>=n) mi2[i][j]=q[h]; } } int ans=2e9; for(int i=n;i<=a;++i) for(int j=n;j<=b;++j) ans=min(ans,mx2[i][j]-mi2[i][j]); printf("%d",ans); }
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 1001 int num[N][N]; int mx[N][N]; int mi[N][N]; int q[N],pos[N],h,t; void read(int &x) { x=0; int f=1; char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } x*=f; } int main() { freopen("data.in","r",stdin); freopen("std.out","w",stdout); int a,b,n; read(a); read(b); read(n); for(int i=1;i<=a;++i) for(int j=1;j<=b;++j) read(num[i][j]); int ans=1e9; for(int i=1;i+n-1<=a;++i) for(int j=1;j+n-1<=b;++j) { int I=i+n-1; int J=j+n-1; int p=1e9,q=-1e9; for(int k=i;k<=I;++k) for(int l=j;l<=J;++l) p=min(p,num[k][l]),q=max(q,num[k][l]); ans=min(ans,q-p); } printf("%d",ans); }
#include<cmath> #include<cstdlib> #include<cstdio> #include<ctime> using namespace std; int main() { freopen("data.in","w",stdout); srand(time(0)+20001024); int a=50,b=60; int n=rand()%10+1; printf("%d %d %d\n",a,b,n); for(int i=1;i<=a;++i) { for(int j=1;j<=b;++j) printf("%d ",rand()); printf("\n"); } }
1047: [HAOI2007]理想的正方形
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3791 Solved: 2095
[Submit][Status][Discuss]
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000
Output
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
Sample Input
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output
1