# [整体二分][二维RMQ] Codeforces 1301E Nanosoft

## Sample Input

5 5 5
RRGGB
RRGGY
YYBBG
YYBBR
RBBRG
1 1 5 5
2 2 5 5
2 2 3 3
1 1 3 5
4 4 5 5


## Sample Output

16
4
4
4
0


## Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

#define RG register int
#define LL long long
const int inf=1e9;

template<typename elemType>
elemType X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
T=(w?-X:X);
}

struct Que{int X1,Y1,X2,Y2,ID;};
Que QUE[300010],Q1[300010],Q2[300010];
int Mat[502][502][4];
int LSum[502][502][4],RSum[502][502][4],USum[502][502][4],DSum[502][502][4];
int RR[502][502],GG[502][502],YY[502][502],BB[502][502],Ex[502][502];
int Ans[300010];
int N,M,Q;

inline void Input(){
char c;
for(RG i=1;i<=N;++i){
for(RG j=1;j<=M;++j){
scanf("%c",&c);
if(c=='R') Mat[i][j][0]=1;
else if(c=='G') Mat[i][j][1]=1;
else if(c=='Y') Mat[i][j][2]=1;
else if(c=='B') Mat[i][j][3]=1;
}
scanf("%c",&c);
}
for(RG i=1;i<=Q;++i){
QUE[i].ID=i;
}
if(N==1||M==1){while(Q--) printf("0\n");}
return;
}

inline void Init(){
for(RG i=1;i<=N;++i){
for(RG j=1;j<=M;++j){
for(RG k=0;k<4;++k){
if(!Mat[i][j][k]) LSum[i][j][k]=0;
else LSum[i][j][k]=LSum[i][j-1][k]+Mat[i][j][k];
if(!Mat[i][M-j+1][k]) RSum[i][M-j+1][k]=0;
else RSum[i][M-j+1][k]=RSum[i][M-j+2][k]+Mat[i][M-j+1][k];
if(!Mat[i][j][k]) USum[i][j][k]=0;
else USum[i][j][k]=USum[i-1][j][k]+Mat[i][j][k];
if(!Mat[N-i+1][j][k]) DSum[N-i+1][j][k]=0;
else DSum[N-i+1][j][k]=DSum[N-i+2][j][k]+Mat[N-i+1][j][k];
}
}
}
for(RG i=1;i<=N;++i){
for(RG j=1;j<=M;++j){
RR[i][j]=min(RR[i-1][j-1]+1,min(LSum[i][j][0],USum[i][j][0]));
GG[i][M-j+1]=min(GG[i-1][M-j+2]+1,min(RSum[i][M-j+1][1],USum[i][M-j+1][1]));
YY[N-i+1][j]=min(YY[N-i+2][j-1]+1,min(LSum[N-i+1][j][2],DSum[N-i+1][j][2]));
BB[N-i+1][M-j+1]=min(BB[N-i+2][M-j+2]+1,min(RSum[N-i+1][M-j+1][3],DSum[N-i+1][M-j+1][3]));
}
}
for(RG i=1;i<=N;++i)
for(RG j=1;j<=M;++j)
Ex[i][j]=min(min(RR[i][j],GG[i][j+1]),min(YY[i+1][j],BB[i+1][j+1]));
}

int maxv[12][12][502][502];
int pre[502];

void Init_RMQ(){
for(RG i=1;i<=N;i++)
for(RG j=1;j<=M;j++)
maxv[0][0][i][j]=Ex[i][j];
pre[2]=pre[3]=1;
for(RG i=4,up=max(N,M);i<=up;i++) pre[i]=pre[i>>1]+1;
int up1=pre[N]+1,up2=pre[M]+1;
for(RG l1=0;l1<=up1;l1++){
for(RG l2=0;l2<=up2;l2++){
if(!l1&&!l2) continue;
for(RG i=1;(i+(1<<l1)-1)<=N;i++){
for(RG j=1;(j+(1<<l2)-1)<=M;j++){
if(l2)maxv[l1][l2][i][j]=max(maxv[l1][l2-1][i][j],maxv[l1][l2-1][i][j+(1<<(l2-1))]);
else maxv[l1][l2][i][j]=max(maxv[l1-1][l2][i][j],maxv[l1-1][l2][i+(1<<(l1-1))][j]);
}
}
}
}
}

int Query(int x1,int y1,int x2,int y2){
if(x1>x2 || y1>y2) return 0;
if(x1==0 || y1==0 || x2==0 || y2==0) return 0;
int p=pre[x2-x1+1],q=pre[y2-y1+1];
int ans=-inf;
ans=max(maxv[p][q][x1][y1],maxv[p][q][x1][y2-(1<<q)+1]);
ans=max(ans,max(maxv[p][q][x2-(1<<p)+1][y1],maxv[p][q][x2-(1<<p)+1][y2-(1<<q)+1]));
return ans;
}
int x1,x2,y1,y2;

void Solve(int L,int R,int x,int y){
if(x>y) return;
if(L==R){
for(register int i=x;i<=y;++i)
Ans[QUE[i].ID]=(L<<1)*(L<<1);
return;
}
int mid=(L+R)>>1,cnt1=0,cnt2=0;
for(register int i=x;i<=y;++i){
int temp=Query(QUE[i].X1+(mid+1)-1,QUE[i].Y1+(mid+1)-1,QUE[i].X2-(mid+1),QUE[i].Y2-(mid+1));
if(temp<mid+1) Q1[++cnt1]=QUE[i];
else Q2[++cnt2]=QUE[i];
}
for(register int i=1;i<=cnt1;++i)
QUE[x+i-1]=Q1[i];
for(register int i=1;i<=cnt2;++i)
QUE[x+cnt1+i-1]=Q2[i];
Solve(L,mid,x,x+cnt1-1);
Solve(mid+1,R,x+cnt1,y);
return;
}

int main(){
Input();
if(N==1||M==1) return 0;
Init();
Init_RMQ();
Solve(0,min(N/2,M/2),1,Q);
for(RG i=1;i<=Q;++i)
printf("%d\n",Ans[i]);
return 0;
}

// RG
// YB

posted @ 2020-02-20 10:51  AE酱  阅读(263)  评论(0编辑  收藏  举报