大家好,我喜欢暴力数据结构,于是使用分块 AC 了此题。
给出
n 个点
(xi,yi),保证
xi,yi 互不相同。求有多少个二元组
(i,j),满足
xi<xj∧yi<yj 且不存在
k 使得
xi<xk<xj∧yi<yk<yj。
n≤2×105。
先离散化。这样横纵坐标都变成
1∼n 的排列。因此相当于平面上有
n 个点
(i,pi)。
那么
(i,j) 这个二元组合法,当且仅当:
- i<j。
- pi<pj。
- ∀k∈(i,j),pk<pi∨pk>pj。
对于一个
i,记能与其产生贡献的
j 从小到大依次为
w1,…,wm。记
S 为
pj>pi 的
i 构成的集合。容易发现:
- w1 是 S 中最小的 j,使得 j>i∧pj>pi。
- 对于 2≤u≤m,wu 是 S 中最小的 j,使得 j>wu−1∧pj<pwu−1。
可以先证明
w 中的点都能与
i 产生贡献,再证明不在
w 中的点都不能与
i 产生贡献。这个结合偏序关系很容易得出。
这启示我们按照
pi 从大到小扫,同时维护
S。记
nxti 为最小的
j 使得
j>i∧pj>pi,这个单调栈扫一遍即可。由于扫到
pi 时,
nxti 一定被加入
S 中。所以
w1=nxti。再记
qi 表示
S 中最小的
j 使得
j>i∧pj<pi。考虑这样一个暴力:从
j=nxti 开始,检查是否合法,再
j←qj。
考虑优化,很难不想到弹飞绵羊。以
B=O(n) 为块长分块。维护
fi,gi 表示从
i 开始跳出所在块到达的位置和跳的次数(包含
i 但不包含
fi)。那么对于每个点就从
j=nxti 开始,每次令答案加上
gj,再令
j←fj。
考虑向
S 中加入
i 后会带来怎样的影响。首先是对
q 的影响,相当于区间
[1,i−1] 内的
qj 要对
i 取
min。对于
i 所在块内的
f,g,直接重构即可,倒着扫这个块,每个
j 的信息从
qj 转移。块内每个点需要单点查询
q,总共
O(nn) 次。因此用一个
O(n)−O(1) 的分块维护
q。
i 右边的块的
f,g 不受影响。至于
i 左边的块,可以发现块中的位置在块内跳的过程是不受影响的,跳出块这一步会受到
i 的影响,因此是
f 数组区间对
i 取
min,
g 不受影响。同样使用
O(n)−O(1) 的分块维护。
时间复杂度
O(nn),空间复杂度
O(n)。
闲话:上一次见到这个题是在 2023 年的 xyd 模拟赛,当时完全没思路。现在还是不会 polylog 做法。不同的是当时一切仍未开始,现在一切已经结束。人生有梦,各自精彩。