先dp求出以每个红色区域右下角为中心的能成为logo的最大半径
然后二维RMQ预处理,之后可O(1)询问任意子矩形中的最大值
最后对于每个询问二分最大logo的半径mid,这样问题就转化成判定是否存在半径大于等于mid的logo,在(x1+mid-1,y1+mid-1,x2-mid,y2-mid)的范围内找最大值判断是否大于等于mid即可
复杂度$O(nmlognlogm+qlog(min(n,m)))$
第一次写二维RMQ,感觉有点类似于树套树,代码量略小于树套树,但容易写挫
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=500+10,mod=1e9+7,inf=0x3f3f3f3f; 5 int n,m,Q,a[N][N],b[N][N],c[N][N],d[4][N][N],r[N][N],ST[N][12][N][12],Log[N]; 6 char s[N][N]; 7 void buildy(int i,int k) { 8 for(int j=1; j<=m; ++j) 9 ST[i][k][j][0]=k==0?r[i][j]:max(ST[i][k-1][j][0],ST[i+(1<<(k-1))][k-1][j][0]); 10 for(int l=1; l<=Log[m]; ++l) 11 for(int j=1; j+(1<<l)-1<=m; ++j) 12 ST[i][k][j][l]=max(ST[i][k][j][l-1],ST[i][k][j+(1<<(l-1))][l-1]); 13 } 14 void build() { 15 for(int i=1; i<=n; ++i)buildy(i,0); 16 for(int k=1; k<=Log[n]; ++k) 17 for(int i=1; i+(1<<k)-1<=n; ++i)buildy(i,k); 18 } 19 int qry(int x1,int y1,int x2,int y2) { 20 int k=Log[x2-x1+1],l=Log[y2-y1+1]; 21 return max(max(ST[x1][k][y1][l],ST[x1][k][y2-(1<<l)+1][l]),max(ST[x2-(1<<k)+1][k][y1][l],ST[x2-(1<<k)+1][k][y2-(1<<l)+1][l])); 22 } 23 int qry2(int x1,int y1,int x2,int y2) { 24 int ret=0; 25 int l=1,r=min((x2-x1+1)/2,(y2-y1+1)/2); 26 while(l<=r) { 27 int mid=(l+r)>>1; 28 if(qry(x1+mid-1,y1+mid-1,x2-mid,y2-mid)>=mid)ret=mid,l=mid+1; 29 else r=mid-1; 30 } 31 return ret*ret*4; 32 } 33 int main() { 34 Log[0]=-1; 35 for(int i=1; i<N; ++i)Log[i]=Log[i>>1]+1; 36 scanf("%d%d%d",&n,&m,&Q); 37 for(int i=1; i<=n; ++i)scanf("%s",s[i]+1); 38 for(int i=1; i<=n; ++i) 39 for(int j=1; j<=m; ++j) { 40 a[i][j]=(s[i][j]=='R'); 41 b[i][j]=(a[i][j]?b[i-1][j]+1:0); 42 c[i][j]=(a[i][j]?c[i][j-1]+1:0); 43 d[0][i][j]=min(min(b[i][j],c[i][j]),d[0][i-1][j-1]+1); 44 } 45 for(int i=1; i<=n; ++i) 46 for(int j=m; j>=1; --j) { 47 a[i][j]=(s[i][j]=='G'); 48 b[i][j]=(a[i][j]?b[i-1][j]+1:0); 49 c[i][j]=(a[i][j]?c[i][j+1]+1:0); 50 d[1][i][j]=min(min(b[i][j],c[i][j]),d[1][i-1][j+1]+1); 51 } 52 for(int i=n; i>=1; --i) 53 for(int j=1; j<=m; ++j) { 54 a[i][j]=(s[i][j]=='Y'); 55 b[i][j]=(a[i][j]?b[i+1][j]+1:0); 56 c[i][j]=(a[i][j]?c[i][j-1]+1:0); 57 d[2][i][j]=min(min(b[i][j],c[i][j]),d[2][i+1][j-1]+1); 58 } 59 for(int i=n; i>=1; --i) 60 for(int j=m; j>=1; --j) { 61 a[i][j]=(s[i][j]=='B'); 62 b[i][j]=(a[i][j]?b[i+1][j]+1:0); 63 c[i][j]=(a[i][j]?c[i][j+1]+1:0); 64 d[3][i][j]=min(min(b[i][j],c[i][j]),d[3][i+1][j+1]+1); 65 } 66 for(int i=1; i<=n; ++i) 67 for(int j=1; j<=m; ++j) 68 r[i][j]=min(min(d[0][i][j],d[1][i][j+1]),min(d[2][i+1][j],d[3][i+1][j+1])); 69 build(); 70 while(Q--) { 71 int x1,y1,x2,y2; 72 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 73 printf("%d ",qry2(x1,y1,x2,y2)); 74 } 75 return 0; 76 }