【做题记录】P6749 Yoshino

  • \(\text{P6749 Yoshino}\)

    • 算法:树套树、线段树、珂朵莉树

题目:

一个长度为 \(n\) 的序列,第 \(i\) 项为 \(a_i\),对数列进行 \(m\) 次操作。

  1. \(l\ r\ x\):把数列下标在 \([l,r]\) 区间内的数赋值为了一个从 \(x\) 开始公差为 \(1\) 的等差数列。

  2. 查询整个数列中的逆序对个数。

\(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)\)

posted @ 2022-01-17 18:34  trsins  阅读(38)  评论(0)    收藏  举报