题解 CF1909H

题意#

给定一个长度为 n 的排列 p。你可以进行不超过 106 次操作,每次操作是选择一个长度为偶数的区间 [l,r],然后交换 (pl,pl+1),(pl+2,pl+3),...,(pr1,pr)

你需要将排列排序。

数据范围:n3×105

题解#

刚才有个群友问我 Z 菜鸡发生肾摸事了,我说怎么回事?给我发了几张 CF 分数对比图,我一看!嗷!原来是昨天,我打了一场 CF,爆零了,掉分到 newbie,又被嘲讽了。

三年之期已到!

提供另一种 2n 次操作的做法。

首先假设 n 是奇数。

我们考虑交替执行 (1,n1)(2,n),执行 n 次,观察执行后的结果。下面是一张做工粗糙的图:

可以发现第 i 号位置被交换到了第 ni+1 上,而且每两条线路都相交了恰好一次。

不妨称终点i 号点的线路为第 i 条线路。

在两条线路相交的时,我们可以选择交换这两条线路的起点。考虑在这些操作中加入这些交换来把排列变成 p

toi=pni+1,并给 itoi 连边,连的边形成一些置换环。一条边 xy 表示我们要把第 x 条线路的起点换到第 y 条线路上。这时,前文的交换线路可以看成是 每个时刻我们都有机会交换一些 toxtoy,且每对 (x,y) 都出现了恰好一次。

我们遇到一对 (x,y) 的时候,如果 xy 在一个置换环上,那么就交换,此时置换环会分裂,xy 就不在一个置换环上了。执行完所有交换后,每两个点都不在一个置换环上,因此一定有 toi=i

由于置换环最多分裂 n1 次,所以这样做最多操作 2n1 次。

然而这还没完:这题 n3×105,所以我们不能暴力做!注意到对于一个置换环,最早的能交换的数对 (x,y) 一定满足 xy 在对置换环的节点排序后相邻,所以只要对于每个环维护一个从小指向大的链表,环分裂的时候把小的那边拿出来删掉并重构即可。

n 是偶数的做法是差不多的,无非是把 (1,n1)(2,n) 换成 (1,n)(2,n1)

时间复杂度 O(nlog2n)O(nlogn),操作次数不超过 2n1

代码

posted @   zhoukangyang  阅读(1204)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2021-01-19 伯努利数 学习笔记
2021-01-19 Pollard-Rho算法 学习笔记
点击右上角即可分享
微信分享提示
主题色彩