CDQ分治
归并排序
在讨论 CDQ 分治之前,我们先说说归并排序。
相信归并排序大家都知道(不会的往这里走 归并排序),如果是对 A [ l . . . r ] A[l...r] A[l...r] 排序,我们可以利用分治算法,设 m i d = ( l + r ) / 2 mid=(l+r)/2 mid=(l+r)/2,分别将左半部分 A [ l . . . m i d ] A[l...mid] A[l...mid] 和右半部分 A [ m i d + 1... r ] A[mid+1...r] A[mid+1...r] 排序,再合并两个子数组,时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)。
逆序对
如果要求逆序对(指当 i < j , A [ i ] > A [ j ] i<j,A[i]>A[j] i<j,A[i]>A[j] 的 ( i , j ) (i,j) (i,j) 的对数)呢?其实,归并排序可以完美化解这个问题。
如果我们仅算 A [ l . . . r ] A[l...r] A[l...r] 中的逆序对,是不是在分治的过程中, A [ l . . . m i d ] A[l...mid] A[l...mid] 和 A [ m i d + 1... r ] A[mid+1...r] A[mid+1...r] 各自内部的逆序对已经算完了?所以我们在合并的时候只用算左半部分和右半部分各取一个数,组成逆序对的对数了。
考虑合并 A [ l . . . m i d ] A[l...mid] A[l...mid] 和 A [ m i d + 1... r ] A[mid+1...r] A[mid+1...r] 的两个指针 i = l . . m i d , j = m i d + 1... r i=l..mid,j=mid+1...r i=l..mid,j=mid+1...r。当 A [ i ] > A [ j ] A[i]>A[j] A[i]>A[j] 时,因为 A [ l . . . m i d ] A[l...mid] A[l...mid] 都已经排好序了,是不是 A [ i . . . m i d ] A[i...mid] A[i...mid] 都是大于 A [ j ] A[j] A[j] 的?所以 i . . . m i d i...mid i...mid 和 j j j 构成了 m i d − i + 1 mid-i+1 mid−i+1