Codeforces #319E: Ping-Pong 题解

博客讲述了如何运用线段树和并查集解决Codeforces #319E的Ping-Pong问题。通过分析区间条件,采用并查集维护联通性,线段树查询相交区间,利用区间长度递增的特性避免错误匹配。讨论了算法复杂度,并解释了处理特殊情况的策略,最后提出判断区间转移的方法。
摘要由CSDN通过智能技术生成

这道题给的一个条件十分奇怪:区间(a,b)能转移到区间(c,d)当且仅当 c<a<d c < a < d or c<b<d c < b < d ,想一下有两种情况符合这个定义

  1. (a,b)与(c,d)互相不包含且有交集
  2. (a,b) (c,d)

这两种情况又有区别:第一种情况下(a,b)和(c,d)互相联通,而第二种情况只能(a,b)–>(c,d). 如果说第一种情况可以用并查集维护的话,第二种情况就十分难处理

另外题目有一个特殊的限制:区间是按照长度从小到大严格递增给出的,这个条件不知道该怎么用


从简单想起
如果只考虑两种情况中的第一种情况,显然可以想到并查集

注意到这样一种关系是可以传递的,所以(a,b)和(c,d)联通后,这个区间相当于变成了一个长区间(min{a,b},max{c,d}),所以我们对并查集的每个节点再维护一个l,r表示最远延伸的左右端点

对于当前区间(ai,bi),如何知道他与哪些区间有相交的部分呢?可以想到线段树,对于之前的每个独立的区间(即并查集中的一棵棵树)在线段树的对应区间上打一个标记,然后查询时将ai和bi分别带入线段树,从根查询到叶子的这条路径上,如果某个节点有标记,说明这个区间包含了ai/bi,则(ai,bi)与原区间有交错

这样处理忽略了一种情况,当(ai,bi) 原某区间时,也会被误查找到,但注意到题目的条件:区间按照长度递增给出,说明之前的区间中不可能有包含当前区间的区间,于是这个问题就解决了

尝试分析这个问题的复杂度,首先这个标记是不会下放的,每个区间打的标记数是logn级别,所以标记的总数是nlogn级别的

再考虑每个标记会被访问多少次,由于一个标记被访问一定会同时进行一个union的操作,所以访问一次之后这个标记就没有价值了,因为之后我们一定会用它的祖先标记。所以每个标记最多被访问一次。这样复杂度有了保证

‘于是这里有一个细节:每次处理完标记以后一定要将标记数组清空,否则复杂度会炸


第一段中的第二种情况还没有考虑,我们尝试分析这样的情况有什么性质

我们设第一种情况的区间移动为A移动,第二种为B移动,那么一个区间到另一个区间的route会是个由A,B构成的字符串

其中全A的部分相当于在并查集中的一棵树中游走

然后我们发现了一个重要的性质:假设有一个集合S,里面的元素是并查集中祖先相同的区间,左右最远端点为l,r;假设存在一个 aS a ∉ S 且a包含S中的某一个元素,那么a一定包含(l,r)

这个结论很好证明,考虑反证法:如果 a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值