solution of CF1411C/CF1465C

网上的一些博客都写到了用并查集维护,把 ( x i , y i ) (x_i,y_i) (xi,yi) 拆成点然后维护连通性的做法, 这里提供一份比较好理解的证明。


首先我们知道,若将一个坐标 ( x i , y i ) (x_i,y_i) (xi,yi) 移动后不会与别的 Rooks 发生冲突,那么我们可以一步移走;

那么如果直接移动到期望的位置后会发生冲突,那么我们就不能移一步了——需要先移一步,然后把会发生冲突的点移到对应位置上,然后再把 ( x i , y i ) (x_i,y_i) (xi,yi) 这个点移动——这样,就需要把 x i , y i x_i,y_i xi,yi 移动两步了。显然,这是这种情况下最优的方案。

于是,我们只需要知道每个棋子移动后是否会发生冲突就好了。这个我们可以用 dfs 之类的东西去做,然而这个复杂度太高了。我们希望找到一种快速而又能准确维护这个信息的方法。

首先我们来看,对于 ( x , y ) (x,y) (x,y) ( i , j ) (i,j) (i,j) ,假设我们移动 ( x , y ) (x,y) (x,y) ,要使其移动后与 ( i , j ) (i,j) (i,j) 发生冲突的条件是什么。

假设我们横着移,那么有 ( x , y ) → ( x , x ) (x,y)\to (x,x) (x,y)(x,x) ,由于数据保证了输入的 ( x , y ) (x,y) (x,y) ( i , j ) (i,j) (i,j) 一定不会冲突,那么有 x ≠ i , y ≠ j x\not= i,y\not= j x=i,y=j;假设横着移动后有了冲突,那么必然有 x = j x=j x=j

同理,假设我们竖着移且移动后产生了冲突,那么必然有 y = i y=i y=i

然后将范围拓宽,我们把每一步次的 ( x i , y i ) (x_i,y_i) (xi,yi) 并入对应的集合(并查集),这个并查集实际上的意义就是行和列的集合。那么它们的祖先也就是它们共同属于的行/列。这么一来,就可以通过并查集中的find操作判断移动后是否产生冲突了。

于是该题可以通过并查集维护的方式优雅解决。

Code.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值