Codeforces Round #619 (Div. 2)E思维+二维RMQ
题:https://codeforces.com/contest/1301/problem/E
题意:给个n*m的图形,q个询问,每次询问问询问区间最大的合法logo的面积是多少
分析:由于logo是由4个同色的小正方形组成的,所以我们先考虑一个数组val[i][j]表示[i][j]位置为‘R' , [i+1][j]位置为’Y‘,[i][j+1]位置为’G‘,[i+1][j+1]位置为’B'所能形成的最大图案边长是多少;
因为这样就只要预处理‘R’正方形沿着左上能形成的最大正方形,“Y”沿着左下能形成的最大正方形,’G‘沿着右上能形成的最大正方形,”B“沿着右下能形成的最大正方形,然后对于位置[i][j]就取min这四者;
对于询问,我们只要二分答案搜到最大符合条件的就行了,注意这里的二分的mid,假设询问[r1,c1,r2,c2],则搜索访问应该在[r1+mid-1,c1+mid-1,r2-mid,c2-mid]的范围内搜索才是合法的;
因为我们在二分时要求满足条件的mid就行,所以这里对val进行倍增处理;
合法性:因为小的合法图案一定在大的合法图案里面,所以对val取的图案也许是超过询问范围,但我们上面已经对询问范围进行如上缩减,所以是合法的
#include<bits/stdc++.h> using namespace std; const int M=505; const int N=10; int ex[4][M][M]; int n,m,q; int val[M][M],f[N][N][M][M],lg[M]; char s[M][M]; void RMQ(int n,int m){ for(int i=0;i<n;i++) for(int j=0;j<m;j++) f[0][0][i+1][j+1]=val[i][j]; for(int i=2;i<M;i++) lg[i]=1+lg[i/2]; for(int i=1;i<=n;i++) for(int k2=1;(1<<k2)<=m;k2++) for(int j=1;j<=m-(1<<k2)+1;j++) f[0][k2][i][j]=max(f[0][k2-1][i][j],f[0][k2-1][i][j+(1<<(k2-1))]); for(int k1=1;(1<<k1)<=n;k1++) for(int i=1;i<=n-(1<<k1)+1;i++) for(int k2=0;(1<<k2)<=m;k2++) for(int j=1;j<=m-(1<<k2)+1;j++) f[k1][k2][i][j]=max(f[k1-1][k2][i][j],f[k1-1][k2][i+(1<<(k1-1))][j]); } int query(int x1,int y1,int x2,int y2){ int k1=lg[x2-x1+1]; int k2=lg[y2-y1+1]; x2=x2-(1<<k1)+1; y2=y2-(1<<k2)+1; return max(f[k1][k2][x1][y1],max(f[k1][k2][x1][y2],max(f[k1][k2][x2][y1],f[k1][k2][x2][y2]))); } bool check(int r1,int c1,int r2,int c2,int midd){ r1=r1+midd-1; c1=c1+midd-1; r2=r2-midd; c2=c2-midd; if(r1>r2||c1>c2) return false; return query(r1,c1,r2,c2)>=midd; } void color(int fx,int fy,char c,int k){///根据进来的参数不同,组成不同方向相同颜色的最大正方形 int stx=0,sty=0; if(fx==-1)stx=n-1; if(fy==-1)sty=m-1; ///while遍历二维数组 while(stx<n&&stx>=0){ while(sty<m&&sty>=0){ if(s[stx][sty]==c){ ex[k][stx][sty]=1; if(stx-fx>=0&&stx-fx<n&&sty-fy>=0&&sty-fy<m){///正方形区域取最小值 if(s[stx-fx][sty]==c&&s[stx][sty-fy]==c&&s[stx-fx][sty-fy]==c){ ex[k][stx][sty]=min(ex[k][stx-fx][sty], min(ex[k][stx][sty-fy],ex[k][stx-fx][sty-fy]))+1; } } } sty+=fy; } sty=0;if(fy==-1)sty=m-1; stx+=fx; } } int main(){ scanf("%d%d%d",&n,&m,&q); for(int i=0;i<n;i++) scanf("%s",s[i]); //1 color(1,1,'R',0); color(-1,1,'Y',1); color(1,-1,'G',2); color(-1,-1,'B',3); for(int i=0;i<n-1;i++){ for(int j=0;j<m-1;j++){ if(s[i][j]=='R'&&s[i+1][j]=='Y'&&s[i][j+1]=='G'&&s[i+1][j+1]=='B'){ val[i][j]=min(ex[0][i][j],min(ex[1][i+1][j],min(ex[2][i][j+1],ex[3][i+1][j+1]))); } } } //2 RMQ(n,m); //3 for(int i=0;i<q;i++){ int r1,c1,r2,c2,ans=0; scanf("%d%d%d%d",&r1,&c1,&r2,&c2); int l=0,r=min(r2-r1,c2-c1); while(l<=r){ int midd=(l+r)>>1; if(check(r1,c1,r2,c2,midd)){ ans=midd; l=midd+1; } else r=midd-1; } printf("%d\n",4*ans*ans); } return 0; }