1 条题解
-
0
自动搬运
来自洛谷,原作者为

LostKeyToReach
争取今年不退役 || int_stl. || 有意互关私。搬运于
2025-08-24 23:08:56,当前版本为作者最后更新于2025-01-28 08:55:32,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本题解提供离线+树状数组+双指针做法,代码请根据思路自行实现。
请务必读完解题思路。
题目回顾
给定 和 ,你有 次询问,每次给出 ,求:
$$\sum_{l \le x \le y \le r}[c \le \text{inv}(x, y) \le d]. $$解题思路
考虑转换原式。
$$\sum_{l \le x \le y \le r}[c \le \text{inv}(x, y) \le d] = \sum_{l \le x \le y \le r} [\text{inv}(x, y) \le d] - \sum_{l \le x \le y \le r} [\text{inv}(x, y) \le c - 1]. $$接下来求解 $\displaystyle \sum_{l \le x \le y \le r} [\text{inv}(x, y) \le d]$。
定义 ,, 为 的前缀和。
-
:表示以 为右端点时最小的 使得 区间的逆序对数量 ,这可以使用「双指针 + 树状数组」的方法来实现,具体思路如下:
- 维护一个窗口 及当前窗口的逆序对数量 ,再开一个树状数组用于维护逆序对数量。
- 枚举 ,每次加入 时将 加上「当前窗口里大于 的数的个数」。
- 如果 ,就移动 向左收缩,同时将 减去「当前窗口里小于 的数的个数」直到 。
- 操作结束后, 便为 。
-
:表示使得 的 的数量,将 求解完毕后计算 即可。
-
:为 的前缀和,表示右端点为 时,有多少个子区间满足 。
对于这部分,我们对 和 分别进行一次这样的计算。
至此,此部分求解完毕,接下来,我们思考一个问题:如何从上述信息,得到「区间 内,有多少子区间的逆序对 」?
固定 ,若我们只关心「右端点 = 」的子区间,逆序对 的那些,其左端点 满足:
故此时子区间数量为:
是现在我们只想要「左端点 且右端点为 」的子区间,这些子区间的数量应该是:
$$f_d(r, l) = \begin{cases} \text{cnt}_d(r), &\quad L_d(r) \ge l,\\ r - l + 1, &\quad L_d(r) < l. \\ \end{cases} $$那么我们再对 中的 求和,便可得区间 内、右端点为 的所有子区间中满足逆序对 的数量。
$$\begin{aligned} \sum_{k = l} ^ r f_d(k, l) &= \sum_{k = l} ^ r \text{cnt}_d(k) - \sum_{k \in S}\left[\text{cnt}_d(k) - (k - l + 1)\right] \\ &=[\text{ps}_d(r) - \text{ps}_d(l - 1)] - \sum_{k \in S}[l - L_d(k)]. \end{aligned} $$其中 。
接下来引入两个变量 和 用于求解 。
$$z_{l, r} = \sum_{k \in [l, r], L_d(k) < l} L_d(k). $$此时 $\displaystyle\sum_{k \in S}[l - L_d(k)] = l \times y_{l, r} - z_{l, r}$。
那么 和 该如何求解?我们发现 这个条件的存在增加了题目难度,那我们不妨开一个桶 , 记录所有 的位置 ,处理询问时将 的 中的位置加入便可以方便地处理掉这个限制。
接下来,我们开两个树状数组 和 分别维护 和 ,加入 的位置时分别单点加 和 即可。
同理,我们对 和 分别做一次。
最后,设我们处理出来的答案为 和 ,直接输出 即可。
时间复杂度分析
- 预处理:。
- 离线计算答案:。
- 总时间复杂度:。
可以轻松处理 的数据。
代码实现
请自行实现。
-
- 1
信息
- ID
- 10982
- 时间
- 1500ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者