洛谷 P2216 [HAOI2007]理想的正方形 題解
阿新 • • 發佈:2018-10-31
一、題目:
二、思路:
二維ST表.
一般二維的ST表是\(f[i][j][k][l]\),表示橫座標為\(i\),往後\(2^k\)個,縱座標為\(j\),往後\(2^l\)次方個,這樣的一個矩形的最大值.
然後看這道題,咦,空間炸了.
再一看,正方形!那還要第四維幹什麼,k和l永遠一樣啊!
類似一維ST表,轉移即可.
三、程式碼:
/* * @Author: 岸芷汀蘭 * @Date: 2018-10-29 22:42:51 * @LastEditors: 岸芷汀蘭 * @LastEditTime: 2018-10-29 22:55:49 * @Description: P2216 of luogu */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; template<class Type> inline Type read(void){ Type 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 f*x; } const int maxn=1005; int n,m,l,map[maxn][maxn],Log[maxn]; int f[maxn][maxn][15],g[maxn][maxn][15],ans=0x3f3f3f3f; inline void init(void){ Log[0]=-1; for(register int i=1;i<=1000;++i)Log[i]=Log[i>>1]+1; for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)f[i][j][0]=g[i][j][0]=map[i][j]; for(register int k=1;k<=11;++k){ for(register int i=1;i<=n-(1<<k)+1;++i){ for(register int j=1;j<=m-(1<<k)+1;++j){ f[i][j][k]=max(max(f[i][j][k-1],f[i+(1<<(k-1))][j][k-1]),max(f[i][j+(1<<(k-1))][k-1],f[i+(1<<(k-1))][j+(1<<(k-1))][k-1])); g[i][j][k]=min(min(g[i][j][k-1],g[i+(1<<(k-1))][j][k-1]),min(g[i][j+(1<<(k-1))][k-1],g[i+(1<<(k-1))][j+(1<<(k-1))][k-1])); } } } } inline int calc(int x,int y){ int tmp1=max(max(f[x][y][Log[l]],f[x][y+l-(1<<Log[l])][Log[l]]),max(f[x+l-(1<<Log[l])][y][Log[l]],f[x+l-(1<<Log[l])][y+l-(1<<Log[l])][Log[l]])); int tmp2=min(min(g[x][y][Log[l]],g[x][y+l-(1<<Log[l])][Log[l]]),min(g[x+l-(1<<Log[l])][y][Log[l]],g[x+l-(1<<Log[l])][y+l-(1<<Log[l])][Log[l]])); return tmp1-tmp2; } int main(){ n=read<int>();m=read<int>();l=read<int>(); for(register int i=1;i<=n;++i) for(register int j=1;j<=m;++j) map[i][j]=read<int>(); init(); for(register int i=1;i<=n-l+1;++i){ for(register int j=1;j<=(m-l+1);++j){ ans=min(ans,calc(i,j)); } } cout<<ans<<endl; return 0; }