Codeforces 1301 E Nanosoft —— 二分+前綴和,求二維區間是否存在

This way

題意:

給你一個n*m的矩陣,每個位置有四種顏色之一。現在每次給你一個矩形範圍的區間,問你其中最大的能作爲標誌的正方形的大小是多少。
標誌一定是這種組成方式:
在這裏插入圖片描述

題解:

這道題我們是要查詢二維區間的最大值,而這個最大值不好維護,因爲區間的限制,會導致最大值可能在區間旁邊的時候,有一部分被裁掉,所以它就不一定是最大值。
那麼我們此時可以二分紅色正方形的邊長,然後查看裏面是否存在滿足答案的標誌,需要注意查詢的區間是給你的區間再往裏縮減mid範圍。
怎麼求區間內是否存在長度爲l的標誌,dp的話需要開4維很明顯不可以,但是前綴和的話只需要三維即可。dp[i][j][k]表示到第i行,第j列,標誌中紅色區域的邊長爲k時,前綴和中有多少個滿足條件的標誌。
那麼處理dp[i][j][k],我們需要先處理sum[i][j][k]:到第i行,第j列,顏色爲k的點的前綴和的數量。然後我們枚舉k去做dp就很方便了。

#include<bits/stdc++.h>
using namespace std;
const int N=5e2+5;
int sum[N][N][4],dp[N][N][N/2];
char s[N][N],mp[4]={'R','G','B','Y'};
int n,m,q;
bool check(int x,int y,int l){
    if(x-l+1<=0||y-l+1<=0||x+l>n||y+l>m)return 0;
    if(sum[x][y][0]-sum[x-l][y][0]-sum[x][y-l][0]+sum[x-l][y-l][0]!=l*l)
        return 0;
    if(sum[x][y+l][1]-sum[x][y][1]-sum[x-l][y+l][1]+sum[x-l][y][1]!=l*l)
        return 0;
    if(sum[x+l][y+l][2]-sum[x+l][y][2]-sum[x][y+l][2]+sum[x][y][2]!=l*l)
        return 0;
    if(sum[x+l][y][3]-sum[x][y][3]-sum[x+l][y-l][3]+sum[x][y-l][3]!=l*l)
        return 0;
    return 1;
}
bool check(int x1,int y1,int x2,int y2,int l){
     return dp[x2][y2][l]-dp[x2][y1-1][l]-dp[x1-1][y2][l]+dp[x1-1][y1-1][l];
}
int main()
{

    scanf("%d%d%d",&n,&m,&q);
    int mx=min(n/2,m/2);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
        for(int j=1;j<=m;j++)
            for(int k=0;k<4;k++)
                sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k]+(s[i][j]==mp[k]);
    }
    int f=check(2,2,2);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=mx;k++)
                dp[i][j][k]=dp[i-1][j][k]+dp[i][j-1][k]-dp[i-1][j-1][k]+check(i,j,k);
    while(q--){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        int l=1,r=min((x2-x1+1)/2,(y2-y1+1)/2),mid,ans=0;
        while(r>=l){
            mid=l+r>>1;
            if(check(x1+mid-1,y1+mid-1,x2-mid,y2-mid,mid))
                ans=mid,l=mid+1;
            else
                r=mid-1;
        }
        printf("%d\n",ans*ans*4);
    }
    return 0;
}

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