Codeforces Round #619 (Div. 2) E. Nanosoft 前缀和
Question:
定义一个logo 形状颜色如下类推 ,现在有一个关于logo的颜色矩阵
长n宽m 并有q次询问:r1,c1 r2,c2 直接最大的logo有多大
n,m<=500 q<=1000;
Solution:
记录每种颜色数量的二维前缀和 ,那么对于一个区域 是否为logo只需分别判断其中颜色数量即可,并且以某个点为起点的logo最多只有一个 ,所以我们可以暴力直接枚举答案长度 和起点一直更新答案即可 时间复杂度为O(min(n,m)/2nm)此题是可以解决的
但当n,m<1000时我们怎么解决呢?
通过观察发现每一个大的logo都包含比他小的logo,满足单调性,考虑二分。
可以预处理出每个点的答案(假设i,j为红色右下角,向四周判断周围的颜色数量复杂度O(nm))后建立一个 二维ST表(O(nmlg(nm)) 查询即可
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define warn printf("!!!***!\n")
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size());
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;
typedef vector<LL> VL;
const int maxn=2e6+6;
const int oo=0x3fffffff;
const int mod=1e9+7;
int n,m,qq,cnt[5][555][555],r1[maxn],c1[maxn],r2[maxn],c2[maxn],ans[maxn];
char s[555][555];
int ask(int k,int r1,int c1,int r2,int c2)
{
return cnt[k][r2][c2]-cnt[k][r2][c1-1]-cnt[k][r1-1][c2]+cnt[k][r1-1][c1-1];
}
int main()
{
scanf("%d%d%d",&n,&m,&qq);
rep(i,1,n){
scanf("%s",s[i]+1);
rep(j,1,m){
if(s[i][j]=='R') cnt[0][i][j]=1;
if(s[i][j]=='G') cnt[1][i][j]=1;
if(s[i][j]=='Y') cnt[2][i][j]=1;
if(s[i][j]=='B') cnt[3][i][j]=1;
}
}
rep(k,0,3){
rep(i,1,n) rep(j,1,m) cnt[k][i][j]+=cnt[k][i-1][j];
rep(i,1,n) rep(j,1,m) cnt[k][i][j]+=cnt[k][i][j-1];
}
rep(i,1,qq) scanf("%d%d%d%d",&r1[i],&c1[i],&r2[i],&c2[i]);
rep(l,1,250) {
if(2*l>n||2*l>m) break;
rep(i,1,n) rep(j,1,m) cnt[4][i][j]=0;
for(int i=1;i<=n-2*l+1;i++) for(int j=1;j<=m-2*l+1;j++){
if(ask(0,i,j,i+l-1,j+l-1)==l*l&&ask(1,i,j+l,i+l-1,j+2*l-1)==l*l
&&ask(2,i+l,j,i+2*l-1,j+l-1)==l*l&&ask(3,i+l,j+l,i+2*l-1,j+2*l-1)==l*l)
cnt[4][i][j]=1;
//cout<<i<<','<<j<<endl;
}
for(int i=1;i<=n-2*l+1;i++) for(int j=1;j<=m-2*l+1;j++) cnt[4][i][j]+=cnt[4][i-1][j];
for(int i=1;i<=n-2*l+1;i++) for(int j=1;j<=m-2*l+1;j++) cnt[4][i][j]+=cnt[4][i][j-1];
rep(i,1,qq) {
if(r2[i]-r1[i]+1>=2*l&&c2[i]-c1[i]+1>=2*l&&ask(4,r1[i],c1[i],r2[i]-l*2+1,c2[i]-l*2+1)){
ans[i]=l;
}
}
}
rep(i,1,qq) printf("%d\n",4*ans[i]*ans[i]);
}