【做题记录】P6749 Yoshino
-
\(\text{P6749 Yoshino}\)
- 算法:树套树、线段树、珂朵莉树
题目:
一个长度为 \(n\) 的序列,第 \(i\) 项为 \(a_i\),对数列进行 \(m\) 次操作。
-
\(l\ r\ x\):把数列下标在 \([l,r]\) 区间内的数赋值为了一个从 \(x\) 开始公差为 \(1\) 的等差数列。
-
查询整个数列中的逆序对个数。
\(n,m\le 3\times 10^4\)。
题解:
考虑逆序对本质。
每次赋值等差序列是不会出现逆序对的。
设当前修改的是 \([l,r]\),那么逆序对个数
\[ans=\sum_{i=l}^r(\sum_{j=1}^{l-1}[a_j>a_i]+\sum_{j=r+1}^n[a_j<a_i])
\]
考虑用树套树去维护。
在线段树的值域缩小的同时,修改区间也随之缩小。
考虑对每个值点建一个树状数组,然后开个桶统计。
然后随便做一下前缀和、区间维护。
对于动态逆序对,其实可以考虑颜色段均摊的思想。
冷静一下,珂朵莉树的 assign 操作,那么将区间变成点,然后暴力维护。
而每次操作除了最初的区间,每次赋值最多只会增加 \([l,r]\) 和其左、右分裂部分。所以最多 \(n+3m\) 个区间。
注意每个区间只操作一次,所以均摊就是 \(O(n\omega)\),其中 \(\omega\) 是单次修改复杂度。
还记得当时开的值域桶,那么用一个树状数组套就可以了。
至于 \(\omega\),朴素地分类计算即可。
实现时注意珂朵莉部分的操作,开三个 set 来统计当前增加区间、分裂的左、右区间。
总的时间复杂度 \(O(n\log^2n)\)。

浙公网安备 33010602011771号