Given an array, lines[] of N pairs of the form (i, j) where (i, j) represents a line segment from coordinate (i, 0) to (j, 1), the task is to find the count of points of intersection of the given lines.
Example:
Input: lines[] = {{1, 2}, {2, 1}}
Output: 1
Explanation: For the given two pairs, the line form (1, 0) to (2, 1) intersect with the line from (2, 0) to (1, 1) at point (1.5, 0.5). Hence the total count of points of intersection is 1.Input: lines[] = {{1, 5}, {2, 1}, {3, 7}, {4, 1}, {8, 2}}
Output: 5
Approach: The given problem can be solved using a Greedy approach using the policy-based data structure. It can be observed that for lines represented b two pairs (a, b) and (c, d) to intersect either (a > c and b < d) or (a < c and b > d) must hold true.Â
Therefore using this observation, the given array of pairs can be sorted in decreasing order of the 1st element. While traversing the array, insert the value of the second element into the policy-based data structure and find the count of elements smaller than the second element of the inserted pair using the order_of_key function and maintain the sum of count in a variable. Similarly, calculate for the cases after sorting the given array of pairs in decreasing order of their 2nd element.
Below is the implementation of the above approach:
C++
// C++ Program of the above approach #include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> using namespace __gnu_pbds; using namespace std; Â
// Defining Policy Based Data Structure typedef tree< int , null_type, Â Â Â Â Â Â Â Â Â Â Â Â Â less_equal< int >, rb_tree_tag, Â Â Â Â Â Â Â Â Â Â Â Â Â tree_order_statistics_node_update> Â Â Â Â ordered_multiset; Â
// Function to count points // of intersection of pairs // (a, b) and (c, d) // such that a > c and b < d int cntIntersections(     vector<pair< int , int > > lines,     int N) {     // Stores the count     // of intersection points     int cnt = 0; Â
    // Initializing Ordered Multiset     ordered_multiset s; Â
    // Loop to iterate the array     for ( int i = 0; i < N; i++) { Â
        // Add the count of integers         // smaller than lines[i].second         // in the total count         cnt += s.order_of_key(lines[i].second); Â
        // Insert lines[i].second into s         s.insert(lines[i].second);     } Â
    // Return Count     return cnt; } Â
// Function to find the // total count of points of // intersections of all the given lines int cntAllIntersections(     vector<pair< int , int > > lines,     int N) {     // Sort the array in decreasing     // order of 1st element     sort(lines.begin(), lines.end(),          greater<pair< int , int > >()); Â
    // Stores the total count     int totalCnt = 0; Â
    // Function call for cases     // with a > c and b < d     totalCnt += cntIntersections(lines, N); Â
    // Swap all the pairs of the array in order     // to calculate cases with a < c and b > d     for ( int i = 0; i < N; i++) {         swap(lines[i].first, lines[i].second);     } Â
    // Function call for cases     // with a < c and b > d     totalCnt += cntIntersections(lines, N); Â
    // Return Answer     return totalCnt; } Â
// Driver Code int main() { Â Â Â Â vector<pair< int , int > > lines{ Â Â Â Â Â Â Â Â {1, 5}, {2, 1}, {3, 7}, {4, 1}, {8, 2} Â Â Â Â }; Â
    cout << cntAllIntersections(lines,                                 lines.size()); Â
    return 0; } |
Java
import java.io.*; import java.lang.*; import java.util.*; // Importing the policy-based data structure import java.util.TreeSet; import java.util.function.*; Â
class Main {     // Function to count points     // of intersection of pairs     // (a, b) and (c, d)     // such that a > c and b < d     static int cntIntersections(Pair[] lines, int N)     {         // Stores the count         // of intersection points         int cnt = 0 ; Â
        // Initializing TreeSet         TreeSet<Integer> s = new TreeSet<Integer>(); Â
        // Loop to iterate the array         for ( int i = 0 ; i < N; i++) { Â
            // Add the count of integers             // smaller than lines[i].second             // in the total count             cnt += s.headSet(lines[i].b, true ).size(); Â
            // Insert lines[i].second into s             s.add(lines[i].b);         } Â
        // Return Count         return cnt;     } Â
    // Function to find the     // total count of points of     // intersections of all the given lines     static int cntAllIntersections(Pair[] lines, int N)     {         // Sort the array in decreasing         // order of 1st element         Arrays.sort(lines, new Comparator<Pair>() {             public int compare(Pair p1, Pair p2)             {                 if (p1.a == p2.a) {                     return p1.b - p2.b;                 }                 return p2.a - p1.a;             }         }); Â
        // Stores the total count         int totalCnt = 0 ; Â
        // Function call for cases         // with a > c and b < d         totalCnt += cntIntersections(lines, N); Â
        // Swap all the pairs of the array in order         // to calculate cases with a < c and b > d         for ( int i = 0 ; i < N; i++) {             int temp = lines[i].a;             lines[i].a = lines[i].b;             lines[i].b = temp;         } Â
        // Function call for cases         // with a < c and b > d         totalCnt += cntIntersections(lines, N); Â
        // Return Answer         return totalCnt;     } Â
    // Driver Code     public static void main(String[] args)     {         Pair[] lines = { new Pair( 1 , 5 ), new Pair( 2 , 1 ),                          new Pair( 3 , 7 ), new Pair( 4 , 1 ),                          new Pair( 8 , 2 ) }; Â
        System.out.println(             cntAllIntersections(lines, lines.length));     } Â
    // Pair class to represent a pair of integers     static class Pair {         int a, b; Â
        Pair( int a, int b)         {             this .a = a;             this .b = b;         }     } } |
Python3
# Python3 implementation of the above approach Â
# Importing in-built module for sorting and bisect_left method from bisect import * Â
# Defining function to count points of intersection of pairs def cntIntersections(lines, N):     # Stores the count of intersection points     cnt = 0 Â
    # Initializing list to store ending points of lines     s = [] Â
    # Loop to iterate the array     for i in range (N):         # Add the count of integers smaller than lines[i][1] in the total count         cnt + = bisect_left(s, lines[i][ 1 ])         # Insert lines[i][1] into s         s.append(lines[i][ 1 ])         s.sort()              # Return Count     return cnt Â
# Function to find the total count of points of intersections of all the given lines def cntAllIntersections(lines, N):     # Sort the array in decreasing order of 1st element     lines = sorted (lines, reverse = True ) Â
    # Stores the total count     totalCnt = 0 Â
    # Function call for cases with a > c and b < d     totalCnt + = cntIntersections(lines, N) Â
    # Swap all the pairs of the array in order to calculate cases with a < c and b > d     lines = [(b, a) for (a, b) in lines] Â
    # Function call for cases with a < c and b > d     totalCnt + = cntIntersections(lines, N) Â
    # Return Answer     return totalCnt Â
# Driver Code if __name__ = = '__main__' : Â Â Â Â lines = [( 1 , 5 ), ( 2 , 1 ), ( 3 , 7 ), ( 4 , 1 ), ( 8 , 2 )] Â Â Â Â print (cntAllIntersections(lines, len (lines))) |
C#
using System; using System.Collections.Generic; Â
public class Program {     // Function to count points     // of intersection of pairs     // (a, b) and (c, d)     // such that a > c and b < d     static int cntIntersections(Pair[] lines, int N)     {         // Stores the count         // of intersection points         int cnt = 0;         // Initializing SortedSet         SortedSet< int > s = new SortedSet< int >(); Â
        // Loop to iterate the array         for ( int i = 0; i < N; i++) {             // Add the count of integers             // smaller than lines[i].second             // in the total count             cnt += s.GetViewBetween( int .MinValue,                                     lines[i].b)                        .Count; Â
            // Insert lines[i].second into s             s.Add(lines[i].b);         } Â
        // Return Count         return cnt;     } Â
    // Function to find the     // total count of points of     // intersections of all the given lines     static int cntAllIntersections(Pair[] lines, int N)     {         // Sort the array in decreasing         // order of 1st element         Array.Sort(lines, new PairComparer()); Â
        // Stores the total count         int totalCnt = 0; Â
        // Function call for cases         // with a > c and b < d         totalCnt += cntIntersections(lines, N); Â
        // Swap all the pairs of the array in order         // to calculate cases with a < c and b > d         for ( int i = 0; i < N; i++) {             int temp = lines[i].a;             lines[i].a = lines[i].b;             lines[i].b = temp;         } Â
        // Function call for cases         // with a < c and b > d         totalCnt += cntIntersections(lines, N); Â
        // Return Answer         return totalCnt;     } Â
    // Driver Code     public static void Main()     {         Pair[] lines = { new Pair(1, 5), new Pair(2, 1),                          new Pair(3, 7), new Pair(4, 1),                          new Pair(8, 2) }; Â
        Console.WriteLine(             cntAllIntersections(lines, lines.Length));     } Â
    // Pair class to represent a pair of integers     public class Pair {         public int a, b; Â
        public Pair( int a, int b)         {             this .a = a;             this .b = b;         }     } Â
    // PairComparer class to compare pairs in decreasing     // order     public class PairComparer : IComparer<Pair> {         public int Compare(Pair p1, Pair p2)         {             if (p1.a == p2.a) {                 return p1.b - p2.b;             }             return p2.a - p1.a;         }     } } |
Javascript
// Defining function to count points of intersection of pairs function cntIntersections(lines, N) {     // Stores the count of intersection points     let cnt = 0; Â
    // Initializing list to store ending points of lines     let s = []; Â
    // Loop to iterate the array     for (let i = 0; i < N; i++) {         // Add the count of integers smaller than lines[i][1] in the total count         cnt += s.filter(x => x < lines[i][1]).length;         // Insert lines[i][1] into s         s.push(lines[i][1]);         s.sort((a, b) => a - b);     } Â
    // Return Count     return cnt; } Â
// Function to find the total count of points of intersections of all the given lines function cntAllIntersections(lines, N) {     // Sort the array in decreasing order of 1st element     lines = lines.sort((a, b) => b[0] - a[0]); Â
    // Stores the total count     let totalCnt = 0; Â
    // Function call for cases with a > c and b < d     totalCnt += cntIntersections(lines, N); Â
    // Swap all the pairs of the array in order to calculate cases with a < c and b > d     lines = lines.map(x => [x[1], x[0]]); Â
    // Function call for cases with a < c and b > d     totalCnt += cntIntersections(lines, N); Â
    // Return Answer     return totalCnt; } Â
// Driver Code let lines = [[1, 5], [2, 1], [3, 7], [4, 1], [8, 2]]; console.log(cntAllIntersections(lines, lines.length)); |
5
Â
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!