CF1905 D,E,F 题解
D:
题意:给出数列a,你可以将a循环移动到任意位置。S为所有位置前缀mex的和,最大化S。
首先猴子都可以看出来每个位置的前缀mex是递增的。
然后我们发现每次将最左边的数字 \(a_i\) 移动到右边时,所有大于 \(a_i\) 的mex值都将变成 \(a_i\) ,再在末尾添加一个 n。
走不通的思路:线段树将大于某个值的所有数改为同一个数,不会,但是发现大于 \(a_i\) 的数都在同一个区间,我们尝试二分找出这个区间的位置,发现也不好找,况且线段树复杂度太高。
Solution:
使用队列,大于 \(a_i\) 的数字都在最右侧,相当于我们压入 \(a_i\) 这个数字时,将最右侧所有大于它的值弹出队列,并将它们全部改为 \(a_i\) 重新压入队列。
这里使用一个小技巧,把所有相同的数字压缩成 “数值+出现次数” 的形式,队列中记录这两个值,就可以做到重复的数字一次性弹出或压入。平均复杂度为O(n)。
E:
题意:给你n,按传统方式构造线段树,对于所有叶子集合,求它们LCA编号的和。(n<=1e18)
Solution:
叶子的集合比较吓人,n 的范围更吓人。
这里有个关键的题意转化:虽然题目是一颗线段树,但我们不能把它当一棵树来看,我们应该把每个叶子看做从 1 到 n 的数字。
每个点成为LCA有哪些情况,即它的左子树内至少选一个叶子,右子树也至少选一个叶子,外面的叶子不选。
转化一下发现就是:如果这个点表示 \([l,r]\) ,那么左子树选一个点就是 \([l,mid]\) 中选一个数,右子树就是 \([mid+1,r]\) 中选一个数,容斥就可以很快算出这个点作为LCA的情况数了。发现这个情况数只与LCA点的长度有关。
做出此题另一个比较关键的点是,虽然题目中说:“In this sad world full of imperfections, ugly segment trees exist.” 但在线段树中,其实每层的点表示的长度只有两个数值。
比如1到53的线段树,第一层长度为53,第二层有长度为27和26的点,第三层有14和13的点,第四层有7和6的点,第五层有4和3的点。。。
所以我们只需要记录每个长度的点的编号和,以及点的数量(方便计算下一层的点)。
用每个长度的点的编号和乘上情况数,求和即为最终答案。
F:
题意:给出排列a,我们称位置 i 为“好的”,当其满足 i 左边的数都小于 i ,i 右边的数都大于 i 。现在你需要交换两个数的位置,最大化好的位置个数。
Solution:
由于是排列,发现好数的必要条件为 \(a_i=i\)。
如果一开始所有位置 \(a_i=i\) ,那么输出 n-2,否则我们交换一定可以使答案不降。
我们有n方种交换方式,不能枚举算出每个交换方式对答案的影响。但仔细思考我们会发现有另一条路,即:使某个位置变成“好的”只有唯一的交换方式。
发现这个性质并不容易,但发现了就相当于这题做出来了。
1:如果这个位置本来就是好的,跳过。
2:如果 \(a_i=i\) ,我们将 i 前面的数中最大值,和 i 后面的数中最小值进行交换,可以用前 i 个数次大值来判断交换后 i 是否变为好的。
3:如果 \(a_i\neq i\),我们交换 \(a_i\) 和 i ,用前最大值来判断交换后 i 是否为好的。
所以每个位置只有一种使答案增加的交换方式,我们可以枚举每个位置计算交换方式,最后统计哪种交换方式对答案的贡献量最大。