这题好像也是咕咕了很久?
题意简述
强制在线的区间逆序对, $n$ 长度 $m$ 查询, $1\le n, m\le 10^5$ 。
题面还保证是排列,更好写(
主要思路
分块,块长为 $O(n)$ ,记录以下几个数组:
- $\langle pre_x\rangle$ :第 $x$ 个元素到所在块的开头一段的逆序对数。
- $\langle suf_x\rangle$ :第 $x$ 个元素到所在块的结尾一段的逆序对数。
- $\langle f_{t, x}\rangle$ :前 $x$ 个元素,每个元素与第 $t$ 块形成的逆序对数总和。注意这里元素若在块中,则钦定可以形成的逆序对数为 $0$ 。
接下来看询问如何解决:
对于跨块的询问,可以拆分成三个区间(两边的散块和中间的一堆整块)。
- 对于两边零散块内部的贡献,处理了 $\langle pre_x \rangle, \langle suf_x \rangle$ ,可以 $O(1)$ 。
- 对于整块内部的贡献,对于每个块求一下与后面的整块形成的逆序对数,这可以通过查 $\langle f_{t, x}\rangle$ 得到;该块内部的贡献和零散块的贡献方法相同。所以单次复杂度 $O(\sqrt{n})$ 。
- 对于零散与中间的整块形成的逆序对,和整块内部贡献类似,查 $\langle f_{t, x}\rangle$ 的表即可 $O(\sqrt{n})$。
- 对于两个零散部分之间形成的逆序对,先对每个块内部排好序,查询时 $O(\sqrt{n})$ 将需要的区间拎出来,然后用双指针可以 $O(\sqrt{n})$ 求出逆序对数。
对于在块内的询问,可以转化为该块的两个前缀的差。当然不能直接 $pre_r - pre_{l - 1}$ ,还要用双指针把这两个段之间产生的贡献减掉。
所以单次查询复杂度就是 $O(\sqrt{n})$ ,可以通过此题。
参考代码
1 |
|