模版:AcWing2815.三维偏序
三维偏序问题:给出三个数组
a
[
]
a[]
a[],
b
[
]
b[]
b[],
c
[
]
c[]
c[]。求所有满足
1
≤
i
,
j
≤
n
1 \le i , j \le n
1≤i,j≤n且
a
[
i
]
≤
a
[
j
]
a[i] \le a[j]
a[i]≤a[j]且
b
[
i
]
≤
b
[
j
]
b[i] \le b[j]
b[i]≤b[j]且
c
[
i
]
≤
c
[
j
]
c[i] \le c[j]
c[i]≤c[j]的数对(i,j)。
将数组按照第一关键字为a,第二关键字为b,第三关键字为c排序,这样 a [ i ] ≤ a [ j ] a[i] \le a[j] a[i]≤a[j]就等价于 i < j i < j i<j。考虑分治计算,假设当前要计算 [ l , r ] [l,r] [l,r]中的三维偏序点对个数,记 m i d = l + r 2 mid = \dfrac{l + r}{2} mid=2l+r,将区间分为 [ l , m i d ] [l,mid] [l,mid]与 [ m i d + 1 , r ] [mid+1,r] [mid+1,r]。若 i , j i,j i,j都在左区间或右区间,都可以递归处理。只需要计算 i i i在左区间, j j j在右区间的方案。这时显然第一个条件永远成立。考虑维护后两个条件,显然并没有一种靠谱的数据结构可以维护他们。发现其实在计算完 [ l , r ] [l,r] [l,r]的三维偏序点对后,实际上 [ l , r ] [l,r] [l,r]中所有点的顺序不需要再按照 a a a来排了。那么就可以在计算完 [ l , r ] [l,r] [l,r]后将之中的所有点按照 b b b来排序,然后每次递归时左右区间都是已经排好序的了,可以使用归并排序将 [ l , r ] [l,r] [l,r]排好。考虑如何计算当前 i i i在左区间, j j j在右区间的三维偏序点对,枚举j,可以双指针找出最靠后的i,那么 [ l , i ] [l,i] [l,i]就是满足 a [ x ] ≤ a [ j ] a n d b [ x ] ≤ b [ j ] a[x] \le a[j] and \ b[x]\le b[j] a[x]≤a[j]and b[x]≤b[j]的所有x,用树状数组维护第三个条件即可。