[bzoj1047][HAOI2007]理想的正方形
给定r,c,n和一个r行c列的矩阵,你需要找到一个n*n的矩形,使得其中的最大值和最小值的差最小 r,c<=1000
题解:
看情况乱搞
线段树先横着查一下每个点后m个的最值,然后竖着搞一遍。
#include<iostream> #include<cstdio> #include<cstring> #define N 1024 #define INF 2000000000 using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int s[1005][1005],s2[1005][1005]; int T[N*2+5],T2[N*2+5]; int n,m,c,ans=INF; int num[1005][1005]; int query2(int l,int r) { int sum=INF; for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) { if(~l&1)sum=min(sum,T2[l+1]); if( r&1)sum=min(sum,T2[r-1]); } return sum; } int query1(int l,int r) { int sum=0; for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) { if(~l&1)sum=max(sum,T[l+1]); if( r&1)sum=max(sum,T[r-1]); } return sum; } void renew1(int x,int ad) { T[x+=N]=ad; for(x>>=1;x;x>>=1) T[x]=max(T[x<<1],T[(x<<1)+1]); } void renew2(int x,int ad) { T2[x+=N]=ad; for(x>>=1;x;x>>=1) T2[x]=min(T2[x<<1],T2[(x<<1)+1]); } int main() { n=read();m=read();c=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) num[i][j]=read(); for(int i=1;i<=n;i++) { memset(T,0,sizeof(T));for(int ii=1;ii<=2*N+1;ii++)T2[ii]=INF; for(int j=m;j;j--) { renew1(j,num[i][j]);renew2(j,num[i][j]); if(j+c-1<=m) s[i][j]=query1(j,j+c-1),s2[i][j]=query2(j,j+c-1); } } //for(int i=1;i<=n;i++) for(int j=1;j+c-1<=m;j++) cout<<i<<" "<<j<<" "<<s[i][j]<<" "<<s2[i][j]<<endl; for(int i=1;i+c-1<=m;i++) { memset(T,0,sizeof(T));for(int ii=1;ii<=2*N+1;ii++)T2[ii]=INF; for(int j=n;j;j--) { renew1(j,s[j][i]);renew2(j,s2[j][i]); if(j+c-1<=n) ans=min(ans,query1(j,j+c-1)-query2(j,j+c-1)); } } cout<<ans; return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream