Gym - 101550A Artwork (并查集在线做法)
题意:给你一个n*m的网格图,初始时格点全白,每次可以将一段连续的格点涂黑。求出每次操作之后白色连通块的数量。
看了看网上的题解,基本全是离线的做法。其实这道题是有在线的做法的,利用了对偶图的性质,适用于任意平面图(大概是)。
(ps:本题思路是我受thu叉院神犇wzf在wannafly冬令营上提到的对偶图思想的启发而想出来的,先膜为敬~~)
我们可以反过来考虑黑格的连通性。假如我们在涂黑某个格点的时候,把两个分离的黑格“连了起来”,这时有两种可能的情况:
1.两黑格在同一连通分量。此时如果将两黑格连接,必将形成一个回路,并且产生一个新的白色连通块。(回路中包着的区域就是一个白色连通块)
2.两黑格不在同一连通分量。此时将两黑格连接不会形成回路,因而也不会产生新的白色连通块。
注意:
1.白格是四连通的,因此对偶图中的黑格应当是八连通的。
2.上面的“连通分量”指的是外侧的连通分量,而不是内侧的连通分量。
例如,假如我们面临下面的状况:

此时,黑格3,4,5已经相连,因此需要把它们看成一个整体,而1,2各自分离,需要单独考虑。我们试图将中间的白色格子涂黑,假设1,2,3,4,5在外侧区域同属于一个连通块,那么中间的白色连通块数量将由原来的一个拆分成3个,分别夹在(1,2),(1,3)和(2,5)之间。
因此我们可以总结出规律:把与中间格点相邻的8个格子中所有的黑格按照顺时针或者逆时针顺序排成一列,把相互八连通的格子放在同一个内侧连通分量中(这个过程可以用另一个并查集实现)。我们把内侧连通分量不同的两个相邻格子两两合并,如果两个格子恰好在外侧同属于一个连通分量,那么必将多出一个“包起来”的白色连通块,此时答案+1。
注意将最后一个连通分量与第一个连通分量合并时不要计算对答案的贡献,因为合并后,原来中间的白色连通块就“消失”了,而它不应该消失,为了不让它消失,需要把这个连通块归结到一个未合并的连通区域中,因此需要保留一个白色连通区域作为原来中间白色连通块的新的“归属”。
最后需要注意的就是如果中间的白格的上下左右四个方向都是黑格,此时中间的白格单独属于一个连通块,在涂黑之后不能归结到任何一个区域,直接就消失了,此时答案应当-1。
还有就是在初始时应当把网格的四周涂黑,简化判断。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+;
const int dx[]= {-,,,,,,-,-};
const int dy[]= {-,-,-,,,,,};
int n,m,nq,fa[N*N],qx[],qy[],fa2[],n2,ans,a[N][N];
int fd(int x,int* fa) {return ~fa[x]?fa[x]=fd(fa[x],fa):x;}
bool mg(int x,int y,int* fa) {
int fx=fd(x,fa),fy=fd(y,fa);
if(fx==fy)return ;
else {fa[fx]=fy; return ;}
}
bool adj(int x1,int y1,int x2,int y2) {//判断是否8连通
return abs(x1-x2)+abs(y1-y2)==||(abs(x1-x2)==&&abs(y1-y2)==);
}
int id(int x,int y) {return x*(m+)+y;}//给格点标号
void solve(int x,int y) {
if(a[x][y])return;
a[x][y]=,n2=;
for(int i=; i<; ++i) {
int xx=x+dx[i],yy=y+dy[i];
if(a[xx][yy])qx[n2]=xx,qy[n2++]=yy;
}//把周围相邻的黑格按顺序扒出来
for(int i=; i<n2; ++i)fa2[i]=-;
for(int i=; i<n2; ++i)
if(adj(qx[i],qy[i],qx[(i+)%n2],qy[(i+)%n2]))mg(i,(i+)%n2,fa2);//合并内侧相邻黑格
for(int i=; i<n2-; ++i)
if(fd(i,fa2)!=fd(i+,fa2)&&fd(i+,fa2)!=fd(,fa2)
&&!mg(id(qx[i],qy[i]),id(qx[i+],qy[i+]),fa))++ans;//如果内侧不连通的黑格在外侧连通,则答案+1
if(a[x][y-]&&a[x][y+]&&a[x-][y]&&a[x+][y])--ans;//中间的格子被包围,答案-1
if(n2)mg(id(qx[],qy[]),id(x,y),fa);//将周围的黑格与中间的格子合并
} int main() {
scanf("%d%d%d",&n,&m,&nq);
memset(fa,-,sizeof fa);
for(int i=; i<=n+; ++i)a[i][]=a[i][m+]=,fa[id(i,)]=fa[id(i,m+)]=;
for(int i=; i<=m+; ++i)a[][i]=a[n+][i]=,fa[id(,i)]=fa[id(n+,i)]=;//将边界格子涂黑并放在同一个连通块
fa[]=-,ans=;
while(nq--) {
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1<x2) for(int i=x1; i<=x2; ++i)solve(i,y1);
else for(int i=y1; i<=y2; ++i)solve(x1,i);
printf("%d\n",ans);
}
return ;
}
Gym - 101550A Artwork (并查集在线做法)的更多相关文章
- Artwork Gym - 101550A 离线并查集
题目:题目链接 思路:每个空白区域当作一个并查集,因为正着使用并查集分割的话dfs会爆栈,判断过于复杂也会导致超时,我们采用离线反向操作,先全部涂好,然后把黑格子逐步涂白,我们把每个空白区域当作一个并 ...
- Codeforces Gym 100463E Spies 并查集
Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...
- Gym - 100676F Palindrome —— 并查集
题目链接:https://vjudge.net/contest/155789#problem/E 题解: 由于是回文串,所以可以先将在对称位置的字符放在同一个集合(如果期间有两个非‘?’,且不相等,则 ...
- POJ1703 && POJ2942 &&POJ 1182 并查集 这个做法挺巧妙
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 37242 Accepted: ...
- 2019-2020 ACM-ICPC Brazil Subregional Programming Contest Problem A Artwork (并查集)
题意:有一个矩形,有\(k\)个警报器,警报器所在半径\(r\)内不能走,问是否能从左上角走到右下角. 题解:用并查集将所有相交的圆合并,那么不能走的情况如下图所示 所以最后查询判断一下即可. 代码: ...
- UVALive 6910 Cutting Tree(并查集应用)
总体来说,这个题给的时间比较长,样例也是比较弱的,别的方法也能做出来. 我第一次使用的是不合并路径的并查集,几乎是一种暴力,花了600多MS,感觉还是不太好的,发现AC的人很多都在300MS之内的过得 ...
- 还是畅通工程(hdu1233)并查集应用
还是畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- 【bzoj4998】星球联盟(并查集+边双)
题面 传送门 题解 总算有自己的\(bzoj\)账号啦! 话说这题好像\(Scape\)去年暑假就讲过--然而我到现在才会-- \(LCT\)什么的跑得太慢了而且我也不会,所以这里是一个并查集的做法 ...
- BZOJ 4516: [Sdoi2016]生成魔咒——后缀数组、并查集
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4516 题意 一开始串为空,每次往串后面加一个字符,求本质不同的子串的个数,可以离线.即长度为 ...
随机推荐
- python通过get方式,post方式发送http请求和接收http响应-urllib urllib2
python通过get方式,post方式发送http请求和接收http响应-- import urllib模块,urllib2模块, httplib模块 http://blog.163.com/xyc ...
- 【备档】客户端自动化(主Android Appium + python
之前做分享写的文档,备档~ 0.移动客户端自动化简介 客户端自动化测试的本质 定位对象 · 操作对象 · 校验对象 对象的定位应该是自动化测试的核心,要想操作.校验一个对象,首先应该识别这个对象. 一 ...
- HTML中常见的其它标签
HTML中常见的其它标签 一.头标签部分 1.<title>:指定浏览器的标题栏显示的内容. 2.<base>: href 属性:指定网页中所有的超链接的目录.可以是本地目录, ...
- Eclipse 汉化方法
1 打开 http://www.eclipse.org/babel/downloads.php 2 复制 http://download.eclipse.org/technology/babel/u ...
- sql 2005 代码导入excel数据
select * into bm from OpenDataSource( 'Microsoft.ACE.OLEDB.12.0', 'Data Source="G:\bm.xls" ...
- Authentication failed (rejected by the remote node), please check the Erlang
官网提供的解决方案 Synchronise Erlang Cookies (when running a manually installedWindows Service) Erlang Secur ...
- 10. Regular Expression Matching *HARD*
Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...
- WinForm窗体下Excel的导入
一.Winform窗体程序的Excel的导入 把Excel导入到内存中的DataTable 方法实现: #region ExcelToDataTable public static DataTable ...
- jQuery旋转插件—rotate-摘自网友
jQuery旋转插件—rotate 时间:2013年01月03日作者:愚人码头查看次数:5,660 views评论次数:6条评论 网上发现一个很有意思的jQuery旋转插件,支持Internet Ex ...
- dubbo监控中心搭建
从网上下载了一个dubbo监控中心,地址忘了,文件名是dubbo-monitor-simple-2.5.3-assembly.tar.gz. 修改监控中心配置文件如下: dubbo.container ...