• [loj3461]Paint by Letters


    将方格(参考题目)看作一个点,相邻的两点若颜色相同则连边,即得到一张网格图,而每次询问即求子矩形内的点导出子图对应的连通块数

    注意到网格图也是平面图,根据欧拉公式有$V+F-E=1+C$(其中$V,F,E$和$C$分别为点数、块数、边数和连通块数),那么不妨去求$V,F$和$E$

    显然$V=(x_{2}-x_{1}+1)(y_{2}-y_{1}+1),E$可以通过二维差分$o(1)$求出($o(nm)$预处理)

    关于$F$,将原网格图中的格子看作一个点,相邻两个格子间有边当且仅当对应的公共边在原图中不存在,由此即得到一张$(n-1)(m-1)$个点的新网格图

    此时的问题类似于求$C$,但不需要考虑与矩形外有边的连通块,因此可以计算

    具体的,记原图中$(x,y),(x,y+1),(x+1,y)$和$(x+1,y+1)$为顶点的方格在新图中对应的点为$(x,y)$,那么问题所求的即是新图中全部在$xin [x_{1},x_{2}),yin [y_{1},y_{2})$这个范围内的连通块数+1

    (注意到不严格在其内部的,必然会与外界成为同一个块)

    可以对每一个连通块求出包含其的极小矩形,但之后的问题并不容易处理

    在每一个连通块中任选一个点,显然连通块全部在该矩形内部的必要条件为该点在矩形内部

    由此,同样二维差分求出这样的连通块数,再枚举矩形更外面一圈,若该点所在的连通块对应的点在矩形内部则将其删除(重复只删除一次)

    时间复杂度为$o(nm+qn+qm)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 #define fi first
     5 #define se second
     6 #define y1 y11
     7 struct Edge{
     8     int nex,to;
     9 }edge[4*N*N];
    10 pair<int,int>pos[N*N];
    11 int n,m,q,V,E,F,scc,x1,y1,x2,y2,sumx[N][N],sumy[N][N],sumf[N][N],head[N*N],bl[N*N],vis[N*N];
    12 char s[N][N];
    13 int id(int x,int y){
    14     if ((!x)||(!y)||(x==n)||(y==m))return 0;
    15     return (x-1)*(m-1)+y;
    16 }
    17 void add(int x,int y){
    18     edge[E].nex=head[x];
    19     edge[E].to=y;
    20     head[x]=E++;
    21 }
    22 void dfs(int k){
    23     if (bl[k])return;
    24     bl[k]=scc;
    25     for(int i=head[k];i!=-1;i=edge[i].nex)dfs(edge[i].to);
    26 }
    27 int main(){
    28     scanf("%d%d%d",&n,&m,&q);
    29     for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
    30     for(int i=2;i<=n;i++)
    31         for(int j=1;j<=m;j++)
    32             sumx[i][j]=sumx[i-1][j]+sumx[i][j-1]-sumx[i-1][j-1]+(s[i][j]==s[i-1][j]);
    33     for(int i=1;i<=n;i++)
    34         for(int j=2;j<=m;j++)
    35             sumy[i][j]=sumy[i-1][j]+sumy[i][j-1]-sumy[i-1][j-1]+(s[i][j]==s[i][j-1]);
    36     memset(head,-1,sizeof(head));
    37     for(int i=0;i<n;i++)
    38         for(int j=0;j<m;j++){
    39             if ((j)&&(s[i+1][j]!=s[i+1][j+1])){
    40                 add(id(i,j),id(i+1,j));
    41                 add(id(i+1,j),id(i,j));
    42             }
    43             if ((i)&&(s[i][j+1]!=s[i+1][j+1])){
    44                 add(id(i,j),id(i,j+1));
    45                 add(id(i,j+1),id(i,j));
    46             }
    47         }
    48     for(int i=0;i<n;i++)
    49         for(int j=0;j<m;j++)
    50             if (!bl[id(i,j)]){
    51                 pos[++scc]=make_pair(i,j);
    52                 dfs(id(i,j));
    53             }
    54     for(int i=1;i<=scc;i++)sumf[pos[i].fi][pos[i].se]=1;
    55     sumf[0][0]=0;
    56     for(int i=1;i<n;i++)
    57         for(int j=1;j<m;j++)sumf[i][j]+=sumf[i-1][j]+sumf[i][j-1]-sumf[i-1][j-1];
    58     for(int i=1;i<=q;i++){
    59         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    60         V=(x2-x1+1)*(y2-y1+1),E=0;
    61         E+=sumx[x2][y2]-sumx[x1][y2]-sumx[x2][y1-1]+sumx[x1][y1-1];
    62         E+=sumy[x2][y2]-sumy[x2][y1]-sumy[x1-1][y2]+sumy[x1-1][y1];
    63         x2--,y2--;
    64         F=sumf[x2][y2]-sumf[x1-1][y2]-sumf[x2][y1-1]+sumf[x1-1][y1-1];
    65         for(int j=y1;j<=y2;j++){
    66             int k=bl[id(x1-1,j)];
    67             if ((x1<=pos[k].fi)&&(pos[k].fi<=x2)&&(y1<=pos[k].se)&&(pos[k].se<=y2)&&(vis[k]!=i)){
    68                 F--;
    69                 vis[k]=i;
    70             }
    71             k=bl[id(x2+1,j)];
    72             if ((x1<=pos[k].fi)&&(pos[k].fi<=x2)&&(y1<=pos[k].se)&&(pos[k].se<=y2)&&(vis[k]!=i)){
    73                 F--;
    74                 vis[k]=i;
    75             }
    76         }
    77         for(int j=x1;j<=x2;j++){
    78             int k=bl[id(j,y1-1)];
    79             if ((x1<=pos[k].fi)&&(pos[k].fi<=x2)&&(y1<=pos[k].se)&&(pos[k].se<=y2)&&(vis[k]!=i)){
    80                 F--;
    81                 vis[k]=i;
    82             }
    83             k=bl[id(j,y2+1)];
    84             if ((x1<=pos[k].fi)&&(pos[k].fi<=x2)&&(y1<=pos[k].se)&&(pos[k].se<=y2)&&(vis[k]!=i)){
    85                 F--;
    86                 vis[k]=i;
    87             }
    88         }
    89         printf("%d
    ",V+F-E);
    90     }
    91     return 0;
    92 }
    View Code
  • 相关阅读:
    【转】Android listview与adapter用法
    【转】 Android Fragment 真正的完全解析(下)
    Jupyter Notebook 基本使用
    斯坦福CS231n学习--初识
    MatConvNet 练习使用CNN
    数据库系统学习(四)- 关系模型之关系代数
    操作系统学习(一)--概述启动过程
    数据库系统学习(三)- 关系模型之基本概念
    数据库系统学习(二)- 基础模型
    数据库系统学习(一)-入门篇
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15253617.html
Copyright © 2020-2023  润新知