1 条题解
-
0
自动搬运
来自洛谷,原作者为

Endt
每个十月十日,都是新的开始。搬运于
2025-08-24 22:28:30,当前版本为作者最后更新于2022-08-26 21:56:04,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Paint by Letters P-题解
题意
一个 的矩形方阵,每一方格有一种目标颜色,颜色相同相邻的方格可以一起被染色, 次询问,求出给且只给某一子矩形方阵染色需要染几次。
前置知识
欧拉平面图定理:, 为连通块个数, 为点集, 为边集, 为区域数。
实现步骤
将可以一起染的连边,题目就是求联通块个数 。
点和边的数量很好求,二维前缀和就能办到,瓶颈在求区域数 。
我们先 找到整个图的独立区域,标记好每一个空格所在的区域编号,然后给每一个区域一个标记点(当然在区域内),如果现在的子图包含了这个标记点,我们就先暂时认为这个区域是存在于图中的。如果事实上它不存在,那唯一的情况是它的边缘在这个子图之外,导致这个区域成为了最外圈的无限区域的一部分,我们可以遍历矩形的边缘,查找部分在边缘内而部分在边缘外的区域,接着检验这个区域的标记点是否在矩形内,若是,将答案减一即可。
噫!好!我们过了!
代码
#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
- 上传者