[Codeforces Round #619][Codeforces 1301E. Nanosoft]

Topic links: 1301E - Nanosoft

Title effect: Given a \ (n \ times n \) four-color matrix, required to answer \ (Q \) times asked: find a maximum square submatrix meet the conditions. A square condition is satisfied if and only if the length of one side is even and his equally into four, each \ (\ frac {1} {4} \) is equal to the size of the square corresponding to the color (upper left 'R' , upper right 'G', the lower left is 'Y', the lower right of 'B'). \ (N, m \ le 500, q \ le 300000 \)

Solution: first glance thought it was strange data structure that was found does not need ...

   Can be found by looking to a point of the top left corner of the square will have at most one, this conclusion can easily prove it, consider this point as the upper-left corner of the sub-matrix, assuming that the current size of the square is \ (x \), then this first row sub-matrix before the \ (\ frac {x} {2} \) column must be 'R', a first row \ (\ frac {x} {2} +1 \) column must be 'G ', regardless \ (X \) is plus or minus, do not allow to meet the conditions of this square.

   So that we can consider how to find a legitimate point to the size of the upper left corner of the square. We can carry out a \ (O (n ^ 3) \) is determined, i.e., while the position and size of the upper left corner of the enumeration, and \ (O (1) \) determines whether the condition is satisfied. There are many ways of determining, my method is directly assigned to each location, the "RGYB" are set to the corresponding \ (6,10 ^ {0,1,10} ^ {12} \), so if four and a section, respectively, equal to the corresponding value is legal. Of course, you can also directly open four arrays recorded separately for each color, four-dimensional seek prefix and can also do that.

   After obtaining each time point corresponding to the upper left corner the answer, we must consider how to answer questions. Due to the same inquiry, different sizes of square will lead to legal changes in the upper left corner of the range, in view of the CF machine to run fast, you can consider \ (O (n) \) to answer every inquiry.

   For each possible answer \ (k \), open a size \ if (n \ times n \) is an array of records each point can be used as the upper left corner of a square of size \ (k \), the summation interval after you can \ (O (1) \) to determine whether there is a legitimate top-left corner of the square within each interval. The inquiry can be different for different size squares response to a query.

   Time complexity: preprocessing \ (O (n ^ 3) \), answer questions \ (O (nq) \)

 

#include<bits/stdc++.h>
using namespace std;
#define N 505
#define LL long long
LL n,m,q,a[N][N],s[N][N],K[4]={0,1,1000000,1000000000000ll},o;
int f[N/2][N][N];
LL get()
{
    char ch=getchar();
    while(ch!='R' && ch!='G' && ch!='Y' && ch!='B')
      ch=getchar();
    if(ch=='R')return 0;
    if(ch=='G')return 1;
    if(ch=='Y')return K[2];
    return K[3];
}
bool check(LL x,LL y,LL X,LL Y,LL k)
{
    LL res=s[X][Y]-s[x-1][Y]-s[X][y-1]+s[x-1][y-1];
    if(o)cout<<x<<" "<<y<<" "<<X<<" "<<Y<<" "<<k<<" "<<res<<endl;
    return res==k*(X-x+1)*(Y-y+1);
}
void init()
{
    for(LL i=1;i<=n;i++)
      for(LL j=1;j<=m;j++)
        a[i][j]=get();
    for(LL i=1;i<=n;i++)
      for(LL j=1;j<=m;j++)
        s[i][j]=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
    for(LL i=1;i<=n;i++)
      for(LL j=1;j<=m;j++)
        if(a[i][j])continue;
        else
          {
          //if(i==2 && j==8)o=1;
          LL res=0;
          for(LL k=1;i+2ll*k-1<=n && j+2ll*k-1<=m;k++)
            if(check(i,j,i+k-1,j+k-1,K[0]) && check(i,j+k,i+k-1,j+2ll*k-1,K[1])
            && check(i+k,j,i+2ll*k-1,j+k-1,K[2]) && check(i+k,j+k,i+2ll*k-1,j+2ll*k-1,K[3]))
              {res=k;break;}
          f[res][i][j]=1;
          a = 0 ;
          }
}
bool fuck(LL x,LL y,LL X,LL Y,LL k)
{
    LL res=f[k][X][Y]-f[k][x-1][Y]-f[k][X][y-1]+f[k][x-1][y-1];
    //cout<<x<<" "<<y<<" "<<X<<" "<<Y<<" "<<k<<" "<<res<<endl;
    return res>0;
}
int ask()
{
    LL x,y,X,Y,w,h,ans=0;
    scanf("%lld%lld%lld%lld",&x,&y,&X,&Y);
    w=X-x+1,h=Y-y+1;
    for(LL i=min(w,h)/2;i>=1;i--)
      if(fuck(x,y,X-2ll*i+1,Y-2ll*i+1,i))
        return printf("%lld\n",4ll*i*i),0;
    return printf("0\n"),0;
}
void rua ()
{
    for(LL k=1;k*2<=min(n,m);k++)
      for(LL i=1;i+2ll*k-1<=n;i++)
        for(LL j=1;j+2ll*k-1<=m;j++)
          f[k][i][j]=f[k][i][j]+f[k][i-1][j]+f[k][i][j-1]-f[k][i-1][j-1];
}
int main ()
{
    scanf("%lld%lld%lld",&n,&m,&q);
    init();
    Street();
    while(q--)ask();
}
View Code

 

Guess you like

Origin www.cnblogs.com/DeaphetS/p/12306097.html