Loading

ARC 080 E 题解

原题传送门

题意:给定一个 \(n\) 的排列 \(a\) 和一个初始为空的序列 \(b\)。你每次需要在 \(a\) 中选择一对相邻的数,把它们从 \(a\) 中拿出来,并按原先的相对顺序插到 \(b\) 的最前面。求字典序最小的 \(b\)

首先你肯定得贪心地把最小的数放在 \(b\) 的最前面。然后你发现一个事情啊,就是说,根据字典序的特性,你每次选择相邻的数对的时候肯定会优先把小的数放在数对的前一个位置,把大的放在后一个位置。所以考虑什么样的数它可以被选择为数对的前一个位置。

假设我们想要在某一刻选择数对 \((a_l,a_r)\),那么 \(l\)\(r\) 的奇偶性必定不同,因为由于我们要选择 \((a_l,a_r)\),所以在选择的时刻它们必须相邻,所以区间 \((l,r)\) 内的数此时一定以及被取完了。然后因为在取区间 \((l,r)\) 的时候,\(l\)\(r\) 都还在,所以区间内部的数不能和外面的数配对,因为它们一定会被 \(l\) 或者 \(r\) 隔开,也就是说这个区间必须“内部消化” \((\) 。然后因为两两配对,所以区间长度必定为偶数,所以 \(l\)\(r\) 的奇偶性必定不同。

所以你每次 \(solve\) 一个区间的时候,这个区间内可以被选为数对的前一个数的位置都是区间内编号为奇数的位置。

所以你可以按奇偶来分开求 \(RMQ\),以此来实现贪心。

然后假设你现在已经贪心地选好了数对中的前一个数 \(a_l\),那你肯定要继续贪心地在区间 \((l,n]\) 当中选一个使得 \(a_r\) 最小的 \(r\) 对吧。那你先输出这个数对,然后你把区间 \([1,l)\)\((l,r)\)\((r,n]\) 加进一个容器里面表示接下来要去 \(solve\) 它们。因为你不同区间的数肯定是不能交叉取的,然后区间之间的 \(solve\) 顺序也不用关心,所以直接无脑往里放就完事儿了。

然后因为你得贪心啊,所以这个容器你得让他实现以一个数对的前一个数为关键字从小到大进行排序,然后每次取出最小的。 \(priority\)_\(queue\)\(set\) 啥的都可以实现。

为什么是前一个数?

因为字典序得先关心前面的东西。

每次怎么得到一个区间内最小的可以作为数对中第一个数的数?

就是前面说的,奇偶分开 \(RMQ\) 随便搞搞就行了,\(ST\) 或者 \(SegmentTree\) 啥的都行。你爱用啥用啥。

\(Code:\)

代码?咕掉,谁爱写谁写。凌晨十二点十三分了,我要困死了,滚去睡觉了。

posted @ 2023-08-29 00:18  MrcFrst  阅读(6)  评论(0编辑  收藏  举报