[Codeforces1301E]Nanosoft

题意

给你一个n×mn\times m的只包含四种颜色的网格。

qq此询问,每次问一个矩阵中所包含的形如以下格式的LogoLogo的最大面积


1n,m500,1q31051\le n,m\le500,1\le q\le3\cdot10^5

题解

1.1.如何确定包含某个点的最大纯色正方形?

只考虑以点(i,j)(i,j)为右下角的颜色为pp的最大正方形的边长,设其为Lp,i,jL_{p,i,j}.

则有:
Lp,i,j={0,colori,jpmin{Lp,i1,j,Lp,i,j1,Lp,i1,j1}+1,colori,j=p L_{p,i,j}=\left\{ \begin{aligned} & 0 & , color_{i,j}\neq p\\ & \min\{L_{p,i-1,j},L_{p,i,j-1},L_{p,i-1,j-1}\}+1 & , color_{i,j}=p \end{aligned}\right.

2.2.如何确定包含某个点的最大的LogoLogo?

考虑红色方块的右下角(i,j)(i,j),则边长为2k2kLogoLogo合法的充要条件为:

LR,i,jk and LG,i,j+kk and LB,i+k,j+kk and LY,i+k,jkL_{R,i,j}\ge k{\rm\ and\ }L_{G,i,j+k}\ge k{\rm\ and\ }L_{B,i+k,j+k}\ge k{\rm\ and\ }L_{Y,i+k,j}\ge k

当存在这样的i,j,ki,j,k满足上述条件时,记Sk,i,j=1S_{k,i,j}=1.

3.3.如何确定某个矩阵内的最大LogoLogo?

先考虑如何判定边长为2k2kLogoLogo是否存在.

因为所记录的(i,j)(i,j)为红色方块的右下角,故可以确定(i,j)(i,j)的选点范围为子矩阵::

r1k+1ir2k,c1k+1jc2kr_1-k+1\le i\le r_2-k,c_1-k+1\le j\le c_2-k

如果存在这样的LogoLogo,也就是子矩阵中存在Sk,i,j=1S_{k,i,j}=1,也就是子矩阵内Sk,i,j>0\sum S_{k,i,j}>0.

可以发现kk的有单调性的,故可以通过二分找到最大的kk.

4.4.考虑另外一种思路

在第二步时记满足条件式的最大的kkfi,jf_{i,j}.

那么在第三步时的判定条件将变为::子矩阵中maxfi,jk\max f_{i,j}\ge k.


总结下来题目体质就是求矩阵和或矩阵最大值.

具体方法为:

a)a)预处理前缀和,差分,时间复杂度O(n3+qlogn)O(n^3+q\log n),空间复杂度O(n3)O(n^3).

inline void Prepare(){
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            for(k=min(min(i,n-i),min(j,m-j));k>=1;--k){
                S[k][i][j]=S[k][i-1][j]+S[k][i][j-1]-S[k][i-1][j-1];
                if(L[0][i][j]>=k&&L[1][i][j+k]>=k&&L[2][i+k][j+k]>=k&&L[3][i+k][j]>=k){
                    for(int l=k;l>=1;--l)
                        S[l][i][j]=S[l][i-1][j]+S[l][i][j-1]-S[l][i-1][j-1]+1;
                    break;
                }
            }
}
inline bool Qry(int x1,int y1,int x2,int y2,int k){
    return S[k][x2][y2]-S[k][x1-1][y2]-S[k][x2][y1-1]+S[k][x1-1][y1-1];
}

b)b)二维STST表,时间复杂度O(n3+qlogn)O(n^3+q\log n),空间复杂度O(n2log2n)O(n^2\log^2n).

inline void Prepare(){
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            for(k=min(min(i,n-i),min(j,m-j));k>=1;--k)
                if(L[0][i][j]>=k&&L[1][i][j+k]>=k&&L[2][i+k][j+k]>=k&&L[3][i+k][j]>=k){
                    f[0][0][i][j]=k;break;
                }
    for(int k=0;k<=Log[n];++k)
        fp(int l=0;l<=Log[m];++l)
            if(k||l)
                for(int i=1;i+(1<<k)-1<=n;++i)
                    for(int j=1;j+(1<<l)-1<=n;++j)
                        f[k][l][i][j]=l?max(f[k][l-1][i][j],f[k][l-1][i][j+(1<<(l-1))]):
                            max(f[k-1][l][i][j],f[k-1][l][i+(1<<(k-1))][j]);
}
inline bool Qry(int x1,int y1,int x2,int y2,int k){
    int Lx=Log[x2-x1+1],Ly=Log[y2-y1+1];
    return k<=max(max(f[Lx][Ly][x1][y1],f[Lx][Ly][x2-(1<<Lx)+1][y2-(1<<Ly)+1]),
            max(f[Lx][Ly][x2-(1<<Lx)+1][y1],f[Lx][Ly][x1][y2-(1<<Ly)+1]));
}

注意:参照点不止右下角一种选法,参照点选取的不同方案只影响子矩阵的范围和判定合法所选取的Lp,x,yL_{p,x,y}.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章