[CF1698F] Equal Reversal 题解

CF link

你谷 link

一道思路非常奇妙的题,当然如果你不考虑证明无脑上也可以通过直觉把这道题给过了。

首先我们考虑这种构造一组解的题目,肯定是第一步找到判定是否有解的充要条件,然后再使用一种满足过程中充要条件不变的系统化求解,即如果充要条件满足,则通过这一种过程,一定能构造出一组解,否则不行。

那么就按部就班来考虑充要条件,首先思考这个翻转操作过程中不变的是什么,是相邻点对的集合,即原来存在一组在位置上相邻,则翻转完后依然会相邻,因为翻转的两端是相同的,那么我们可以大胆猜想,是否只要相邻点对的集合相同,就一定有解呢?已经非常接近了,还有一个非常浅显的条件,就是首尾相同,这样是否就一定正确呢?可以尝试证明。

这里需要一些思想的火花,非常奇妙地,我们考虑一个很少用到的模型——欧拉路模型。

我们将给定的数组看成一条欧拉路,将每个值作为节点,相邻的两个值之间看成一条边,那么上面的相邻点对的集合相同就等价于图的形态相同,然后翻转操作等价于找到一个环路径将其翻转,证明过程就变成给定两条欧拉路,问是否能通过对环路径进行翻转使两路径相同,首先欧拉路的起点和终点必须是相同的,对应上面的首尾相同,否则显然一定可以可以构造的,构造方法即后面讲到的本题的构造方法。

我们顺序对 \(a\) 数组进行操作,使其从前往后慢慢变成 \(b\) 数组,那么考虑每遇到一个 \(a_i\ne b_i\),此时一定满足 \(\forall k\in[1,i)\cap\mathbb Z,\ a_k=b_k\),那么我们考虑在不破坏前面的情况下将 \(a_i\) 变换成 \(b_i\),如果后面存在一个 \(j\) 满足 \(a_j=b_i,a_{j+1}=b_{i-1}\),显然我们可以将 \([i-1,j+1]\) 区间反转,至于之后部分,因为之后的部分依然满足边集相同,所以我们可以利用类似数学归纳法的思想去解决这个问题,因为边集相同,所以 \(b_{i-1}\)\(b_i\) 之间一定有边,那么既然在 \(a\) 中不存在一组 \(a_j=b_i,a_{j+1}=b_{i-1}\),那肯定存在至少一个 \(j\) 满足 \(a_j=b_i,a_{j-1}=b_{i-1}\),一个非常显然地思路是找到一组 \(u,v\) 满足 \(a_u=a_v,u\in(i,j],v\in(j,n]\),然后翻转区间 \(u,v\),那么同时 \(a_{j-1}\)\(a_j\) 之间的位置关系就会反过来,最后就可以直接像上一种情况一样直接翻转,在图中,这种操作对应找一个包含这条边的环,并将环翻转,那么问题转变成这样一个环存不存在,事实上一定是存在的,欧拉路上不在环上的边只可能在从起点到终点的一条链上,假设这条边出现在链上(显然这条边只能出现一次,否则必然成环),那么这条边将整张图分成不相交的两个部分,分别包含起点和终点,因为两张图的形态相同,所以两边形态分别相同,而与起点相连的部分路径构造完毕,两条路径的端点都应该在这条边上,那我们根本就不需要去操作了,与实际情况不符,我们就自然地排除了这种情况。

那么讲完了原理,实际实现上更为简单,我们可以直接构造,刚刚我们发现了我们构造出图的方式是充要的,那么如果构造过程中发现无法构造,就可以直接判断无解,同时构造过程中有几个特点,首先,在第二种情况下,即需要找一个 \(j\) 满足 \(a_j=b_i,a_{j-1}=b_{i-1}\),若有多个 \(j\) 满足要求,我们只要直接找第一个就好了,证明可以用上面的结论,其实还有更加简单的办法,如果有多个 \(j\) 满足要求,则可以直接去下一个 \(j\),设为 \(j'\),满足 \(a_{j'-1}=a_{j-1}\),可以直接用这个 \(j'\) 将我们的第一个 \(j\) 翻转,构造答案。

代码并没有想象中那么复杂,时间复杂度是 \(\mathcal O\left(n^3\right)\),瓶颈是要找到一组 \(u,v\) 来翻转。

posted @ 2022-07-09 10:42  老莽莽穿一切  阅读(67)  评论(0编辑  收藏  举报