I have a problem like this:
we have an array of elements like this :
(a0,b0)
(a1,b1)
.
.
.
(an,bn)
and I wanna find the number of elements which have one of this two condition:
1) if ai>aj and bi<bj then:count:=count+1
or
2)if ai<aj and bi>bj then:count:=count+1
I've already found an algorithm that is O(n^2), but I need the faster algorithm
Example: suppose we have this:
(1,5)
(4,7)
(8,2)
I wanna find the number of time that condition satisfied, so 1<8 and 2<5 so condition is satisfied but 1<4 and 5<7 so condition is not satisfied.
This can be accomplished by divide-and-conquer, and if done well (essentially, avoiding multiple sorts by using merge in each pass), this will be $O(n\cdot \log{n})$. Throughout this solution it is helpful to imagine these tuples as points on a $2D$ Cartesian plane which $a_i$s being the horizontal $x$-coordinate and $b_i$s being the vertical $y$-coordinates: thus the left/right notions refer to comparisons in $a_i$s while upper/lower notions refer to comparisons in $b_i$s.
This is a recursive solution, here is the pseudocode:
Explanation:
We first sort our array by the $a_i$s and call $numpair()$ with this sorted array. The recursive function calls the left and right halves of this array in turn and thus gets the number of pairs where both members lie on the left or on the right. These calls also return the left and right subarrays (which we passed sorted by $a_i$s), now sorted by $b_i$s
Now we run a merge sequence for these returned $b_i$-sorted subarrays while now also counting pairs that have one member in the left and one in the right. We use a two pointer method: we keep each pointer on left and right at their lowest values (by $b_i$s) and increment the one which has the lower $b_i$ between the two. At any time we see the left point at greater $b_i$ than the right one, we increment our cross-pairs count. Now here comes a little twist: we actually increment every time by a quantity $oldpoints+1$. Here is why:
At the end we return the total number of pairs we counted on the left and right (by recursion) and the cross-partition pairs we counted via the merge sequence as the total number of pairs and also return the input array sorted by $b_i$s to tie up the recursion. The first element we returned is the actual answer.
Time Complexity:
Denote this as a function of input size $n$ as $T(n)$ and observe that the merge process is $O(n)$. So for the function, complexity: $$T(n) = 2T(n / 2) + O(n)$$ This, as we know (just like in merge sort) resolves to $O(n\cdot \log{n})$. And this doesn't change when you count the initial sort by $a_i$s, we do on the parent array before calling the function. So yeah, a properly designed divide-and-conquer achieves this in $O(n\cdot \log{n})$