1 条题解

  • 0
    @ 2025-8-24 22:28:30

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Endt
    每个十月十日,都是新的开始。

    搬运于2025-08-24 22:28:30,当前版本为作者最后更新于2022-08-26 21:56:04,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    Paint by Letters P-题解

    题意

    一个 n×mn\times m 的矩形方阵,每一方格有一种目标颜色,颜色相同相邻的方格可以一起被染色,qq 次询问,求出给且只给某一子矩形方阵染色需要染几次。

    前置知识

    欧拉平面图定理:K=VE+R1K=|V|-|E|+R-1KK 为连通块个数,VV 为点集,EE 为边集,RR 为区域数。

    实现步骤

    将可以一起染的连边,题目就是求联通块个数 KK

    点和边的数量很好求,二维前缀和就能办到,瓶颈在求区域数 RR

    我们先 bfsbfs 找到整个图的独立区域,标记好每一个空格所在的区域编号,然后给每一个区域一个标记点(当然在区域内),如果现在的子图包含了这个标记点,我们就先暂时认为这个区域是存在于图中的。如果事实上它不存在,那唯一的情况是它的边缘在这个子图之外,导致这个区域成为了最外圈的无限区域的一部分,我们可以遍历矩形的边缘,查找部分在边缘内而部分在边缘外的区域,接着检验这个区域的标记点是否在矩形内,若是,将答案减一即可。

    噫!好!我们过了!

    代码

    #include<bits/stdc++.h>
    
    #define  Int  long long int
    #define  Pub  public
    
    using std::min;using std::max;
    
    int n,m,q;
    char p[1005][1005];
    std::pair<int,int> s[1005][1005][5];
    
    bool vis[1005][1005],siv[2000005];
    int v[1005][1005],e1[1005][1005],e2[1005][1005],r[1005][1005];
    int rid[1005][1005],cnt;
    std::pair<int,int> t[1000005];
    void dfs(int x,int y){
        if(x<0||x>n||y<0||y>m)return;
        if(vis[x][y])return;
        else vis[x][y]=1;
        if(s[x][y][3]==std::pair<int,int>{0,0})rid[x][y-1]=rid[x][y],dfs(x,y-1);
        if(s[x][y][4]==std::pair<int,int>{0,0})rid[x-1][y]=rid[x][y],dfs(x-1,y);
        if(s[x+1][y+1][1]==std::pair<int,int>{0,0})rid[x][y+1]=rid[x][y],dfs(x,y+1);
        if(s[x+1][y+1][2]==std::pair<int,int>{0,0})rid[x+1][y]=rid[x][y],dfs(x+1,y);
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;++i)
            for(int j=(getchar(),1);j<=m;++j)
                p[i][j]=getchar();
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                int vvv=1,ee1=0,ee2=0;
                if(p[i][j]==p[i-1][j])s[i][j][1]={i-1,j},++ee2;
                if(p[i][j]==p[i][j-1])s[i][j][2]={i,j-1},++ee1;
                if(p[i][j]==p[i+1][j])s[i][j][3]={i+1,j};
                if(p[i][j]==p[i][j+1])s[i][j][4]={i,j+1};
                v[i][j]=v[i-1][j]+v[i][j-1]-v[i-1][j-1]+vvv;
                e1[i][j]=e1[i-1][j]+e1[i][j-1]-e1[i-1][j-1]+ee1;
                e2[i][j]=e2[i-1][j]+e2[i][j-1]-e2[i-1][j-1]+ee2;         
            }
        }
        for(int i=0;i<=n;++i){
            for(int j=0;j<=m;++j){
                if(i==0&&j==0)r[i][j]=0;
                else if(i==0||j==0)r[i][j]=1;
                else r[i][j]+=r[i-1][j]+r[i][j-1]-r[i-1][j-1];
                if(vis[i][j])continue;
                else{
                    ++cnt;
                    rid[i][j]=cnt;
                    t[cnt]=std::pair<int,int>{i,j};
                    ++r[i][j];
                    dfs(i,j);
                }
            }
        }
        
        while(~--q){
            memset(siv,0,sizeof(siv));
            int x_,y_,_x,_y;
            scanf("%d%d%d%d",&x_,&y_,&_x,&_y);
            int ans=0;
            ans+=v[_x][_y]+v[x_-1][y_-1]-v[x_-1][_y]-v[_x][y_-1];
            ans-=e1[_x][_y]+e1[x_-1][y_]-e1[x_-1][_y]-e1[_x][y_];
            ans-=e2[_x][_y]+e2[x_][y_-1]-e2[x_][_y]-e2[_x][y_-1];
            ans+=r[_x-1][_y-1]+r[x_-1][y_-1]-r[x_-1][_y-1]-r[_x-1][y_-1];
            for(int i=x_;i<_x;++i)
                if(s[i][y_][3]==std::pair<int,int>{0,0})
                    if(t[rid[i][y_]].first>=x_&&t[rid[i][y_]].first<_x&&t[rid[i][y_]].second>=y_&&t[rid[i][y_]].second<_y&&!siv[rid[i][y_]])
                        siv[rid[i][y_]]=1,--ans;
            for(int i=y_;i<_y;++i)
                if(s[x_][i][4]==std::pair<int,int>{0,0})
                    if(t[rid[x_][i]].first>=x_&&t[rid[x_][i]].first<_x&&t[rid[x_][i]].second>=y_&&t[rid[x_][i]].second<_y&&!siv[rid[x_][i]])
                        siv[rid[x_][i]]=1,--ans;
            for(int i=x_;i<_x;++i)
                if(s[i][_y][3]==std::pair<int,int>{0,0})
                    if(t[rid[i][_y]].first>=x_&&t[rid[i][_y]].first<_x&&t[rid[i][_y]].second>=y_&&t[rid[i][_y]].second<_y&&!siv[rid[i][_y]])
                        siv[rid[i][_y]]=1,--ans;
            for(int i=y_;i<_y;++i)
                if(s[_x][i][4]==std::pair<int,int>{0,0})
                    if(t[rid[_x][i]].first>=x_&&t[rid[_x][i]].first<_x&&t[rid[_x][i]].second>=y_&&t[rid[_x][i]].second<_y&&!siv[rid[_x][i]])
                        siv[rid[_x][i]]=1,--ans;
            printf("%d\n",ans);
        }
        
        return 0;
    }
    
    • 1

    信息

    ID
    6445
    时间
    1500ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    0
    已通过
    0
    上传者