其他分享
首页 > 其他分享> > 18th浙江省赛J

18th浙江省赛J

作者:互联网

18th浙江省赛J

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/16079733.html