18th浙江省赛G
作者:互联网
18th浙江省赛G
G .Wall Game
不知道为啥这题在CF里这么奇怪
题目大意:
一个蜂窝状的地图,每一格是一个正六边形,两个格共用一条边则为相邻。
操作1表示占领 (x,y)。操作2表示查询(x,y)的连通块的边界长度 。
思路和代码:
一开始我也想并查集,但是有两个问题:
1)这是二维的,ai的范围还贼大,我本来还想开n2的表然后用一个pair表示每一个点,但是这样M会爆炸。
2)我不知道怎么去维护连通块的边界长度(没有想下去啊)。
在神牛队友潘的提醒下,我发现了题目说最多就n个点。又想到在线段树和Trie中常用的给节点标号的做法。所以在占领新的坐标时,给其一个新的编号即可。但是还是因为xy太大,肯定是不能用二维数组的,所以可以用map。
再就是维护连通块边界的做法。
1)当两个块ab不连通,要给他并在一起的时候,我们发现最后大块的边界长度就是lena+lenb-2,至于为什么,自己动笔画几个8~
2)当两个块ab连通,我们发现要对大块直接-2,至于为什么,自己动笔画个图8~
ll n , m , idx ;
ll ans[N] , fa[N] ;
map<pll , ll> mp ;
ll dx[6] = {1 , 1 , 0 , 0 , -1 , -1} ;
ll dy[6] = {-1 , 0 , -1 , 1 , 0 , 1} ;
ll find(ll now){
return fa[now] = fa[now] == now ? now : find(fa[now]) ;
}
void solve(){
ll op , x , y ;
cin >> op >> x >> y ;
if(op == 2){
cout << ans[find(mp[{x , y}])] << "\n" ;
}else{
mp[{x , y}] = ++ idx ;
fa[idx] = idx ;
ans[idx] = 6 ;
rep(i , 0 , 5){
ll nx = x + dx[i] ;
ll ny = y + dy[i] ;
if(!mp[{nx , ny}]) continue ;
// debug ;
ll fnow = find(mp[{x , y}]) ;
ll fnxt = find(mp[{nx , ny}]) ;
if(fnxt == fnow) ans[fnow] -= 2 ;
else{
fa[fnxt] = fnow ;
ans[fnow] += ans[fnxt] - 2 ;
}
}
}
}//code_by_tyrii
小结:
说实话这是我碰到最难的一个裸并查集种类并查集还是不会
1)省赛这样的正式比赛是一场马拉松,打了一两个小时很容易就疲惫了,这时候更要多动笔,像这题维护连通块边长的方法动动笔画一下很容易就能发现。
2)还有就是节点标号的处理,值得点赞。
3)千万不要怕繁琐!!!
标签:连通,ll,查集,fa,18th,now,浙江省,op 来源: https://www.cnblogs.com/tyriis/p/16079730.html