Open In App

Count of intersections of M line segments with N vertical lines in XY plane

Given x coordinates of N vertical lines (parallel to Y-axis) and M line segments extending from (x1, y1) to (x2, y2), the task is to find the total number of intersections of the line segments with the vertical lines.

Examples: 

Input: N = 2, M = 1, lines[] = {-1, 1}, Segments[][4] = {0, 1, 2, 1} 
Output:
Explanation: 
There is only one point of intersection (1, 1) 
 

Input: N = 4, M = 8, lines[] = {-5, -3, 2, 3}, segments[][4] = {{-2, 5, 5, -6}, {-5, -2, -3, -5}, {-2, 3, -6, 1}, {-1, -3, 4, 2}, { 2, 5, 2, 1}, { 4, 5, 4, -5}, {-2, -4, 5, 3}, { 1, 2, -2, 1}}; 
Output:
Explanation: 
There are total of 8 intersections. 
Dotted lines are the vertical lines. 
A green circle denote a single point of intersection and 
a green triangle denotes that two line segments 
intersect same vertical line at that point. 
 

Naive Approach: 
The simplest approach is, for each query, check if a vertical line falls between the x-coordinates of the two points. Thus, each segment will have O(N) computational complexity. 

Time complexity: O(N * M)
Approach 2: The idea is to use Prefix Sum to solve this problem efficiently. Follow the steps below to solve the problem: 

Below is the implementation of the above approach. 




// C++ implementation for the
// above approach.
#include <bits/stdc++.h>
using namespace std;
 
// Function to create prefix sum array
void createPrefixArray(int n, int arr[],
                       int prefSize,
                       int pref[])
{
    // Initialize the prefix array
    // to remove garbage values
    for (int i = 0; i < prefSize; i++) {
        pref[i] = 0;
    }
 
    // Marking the occurrences of
    // vertical lines
    for (int i = 0; i < n; i++) {
        // x is the value after
        // Index mapping
        int x = arr[i] + 1000000;
        pref[x]++;
    }
 
    // Creating the prefix array
    for (int i = 1; i < prefSize; i++) {
        pref[i] += pref[i - 1];
    }
}
 
// Function returns the count of
// total intersection
int pointsOfIntersection(int m,
                         int segments[][4],
                         int size,
                         int pref[])
{
 
    // ans is the number of points of
    // intersection of the line segments
    // with the vertical lines
    int ans = 0;
 
    for (int i = 0; i < m; i++) {
        int x1 = segments[i][0];
        int x2 = segments[i][2];
 
        // Index mapping
        x1 = x1 + 1000000;
        x2 = x2 + 1000000;
 
        // We don't consider a vertical
        // line segment because even if
        // it falls on a vertical line
        // then it just touches it and
        // not intersects.
        if (x1 != x2) {
            // We have assumed that x1
            // will be left and x2 right
            // but if not then we just
            // swap them
            if (x1 > x2) {
                swap(x1, x2);
            }
 
            int Occ_Till_Right = pref[x2 - 1];
            int Occ_Till_Left = pref[x1];
 
            ans = ans + (Occ_Till_Right
                         - Occ_Till_Left);
        }
    }
    return ans;
}
 
int main()
{
 
    // N is the number of vertical lines
    // M is the number of line segments
    int N = 4;
    int M = 8;
 
    int size = 2000000 + 2;
    int pref[size];
 
    int lines[N] = { -5, -3, 2, 3 };
 
    // Format : x1, y1, x2, y1
    int segments[M][4] = { { -2, 5, 5, -6 },
                           { -5, -2, -3, -5 },
                           { -2, 3, -6, 1 },
                           { -1, -3, 4, 2 },
                           { 2, 5, 2, 1 },
                           { 4, 5, 4, -5 },
                           { -2, -4, 5, 3 },
                           { 1, 2, -2, 1 } };
 
    // First create the prefix array
    createPrefixArray(N, lines, size, pref);
 
    // Print the total number of intersections
    cout << pointsOfIntersection(M, segments,
                                 size, pref)
         << endl;
 
    return 0;
}




// Java implementation for the
// above approach.
import java.util.*;
 
class GFG{
 
// Function to create prefix sum array
static void createPrefixArray(int n, int arr[],
                              int prefSize,
                              int pref[])
{
     
    // Initialize the prefix array
    // to remove garbage values
    for(int i = 0; i < prefSize; i++)
    {
        pref[i] = 0;
    }
 
    // Marking the occurrences of
    // vertical lines
    for(int i = 0; i < n; i++)
    {
         
        // x is the value after
        // Index mapping
        int x = arr[i] + 1000000;
        pref[x]++;
    }
 
    // Creating the prefix array
    for(int i = 1; i < prefSize; i++)
    {
        pref[i] += pref[i - 1];
    }
}
 
// Function returns the count of
// total intersection
static int pointsOfIntersection(int m,
                                int segments[][],
                                int size,
                                int pref[])
{
 
    // ans is the number of points of
    // intersection of the line segments
    // with the vertical lines
    int ans = 0;
 
    for(int i = 0; i < m; i++)
    {
        int x1 = segments[i][0];
        int x2 = segments[i][2];
 
        // Index mapping
        x1 = x1 + 1000000;
        x2 = x2 + 1000000;
 
        // We don't consider a vertical
        // line segment because even if
        // it falls on a vertical line
        // then it just touches it and
        // not intersects.
        if (x1 != x2)
        {
             
            // We have assumed that x1
            // will be left and x2 right
            // but if not then we just
            // swap them
            if (x1 > x2)
            {
                int temp = x1;
                x1 = x2;
                x2 = temp;
            }
 
            int Occ_Till_Right = pref[x2 - 1];
            int Occ_Till_Left = pref[x1];
 
            ans = ans + (Occ_Till_Right -
                         Occ_Till_Left);
        }
    }
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
 
    // N is the number of vertical lines
    // M is the number of line segments
    int N = 4;
    int M = 8;
 
    int size = 2000000 + 2;
    int []pref = new int[size];
 
    int lines[] = { -5, -3, 2, 3 };
 
    // Format : x1, y1, x2, y1
    int segments[][] = { { -2, 5, 5, -6 },
                         { -5, -2, -3, -5 },
                         { -2, 3, -6, 1 },
                         { -1, -3, 4, 2 },
                         { 2, 5, 2, 1 },
                         { 4, 5, 4, -5 },
                         { -2, -4, 5, 3 },
                         { 1, 2, -2, 1 } };
 
    // First create the prefix array
    createPrefixArray(N, lines, size, pref);
 
    // Print the total number of intersections
    System.out.print(pointsOfIntersection(M, segments,
                                  size, pref) + "\n");
}
}
 
// This code is contributed by Amit Katiyar




# Python3 implementation for the
# above approach
 
# Function to create prefix sum array
def createPrefixArray(n, arr, prefSize, pref):
 
    # Initialize the prefix array
    # to remove garbage values
    for i in range(prefSize):
        pref[i] = 0
 
    # Marking the occurrences
    # of vertical lines
    for i in range(n):
        x = arr[i] + 1000000
        pref[x] += 1
 
    # Creating the prefix array
    for i in range(1, prefSize):
        pref[i] += pref[i - 1]
 
# Function that returns the count
# of total intersection
def pointOfIntersection(m, segments, size, pref):
 
    # ans is the number of points of
    # intersection of the line segments
    # with the vertical lines
    ans = 0
 
    for i in range(m):
        x1 = segments[i][0]
        x2 = segments[i][2]
 
        # Index mapping
        x1 = x1 + 1000000
        x2 = x2 + 1000000
 
        # we don't consider a vertical 
        # line segment because even if
        # it falls on a vertical line
        # then it just touches it and
        # not intersects.
        if (x1 != x2):
             
            # We have assumed that x1
            # will be left and x2 right
            # but if not then just swap
            if (x1 > x2):
                x1, x2 = x2, x1
 
            Occ_Till_Right = pref[x2 - 1]
            Occ_Till_Left = pref[x1]
 
            ans += (Occ_Till_Right - Occ_Till_Left)
 
    return ans
 
# Driver code
 
# Number of vertical lines
N = 4
 
# Number of line segments
M = 8
 
size = 2000000 + 2
pref = [0] * size
lines = [ -5, -3, 2, 3 ]
 
# Format : x1, y1, x2, y2
segments = [ [ -2, 5, 5, -6 ],
             [ -5, -2, -3, -5 ],
             [ -2, 3, -6, 1 ],
             [ -1, -3, 4, 2 ],
             [ 2, 5, 2, 1 ],
             [ 4, 5, 4, -5 ],
             [ -2, -4, 5, 3 ],
             [ 1, 2, -2, 1 ] ]
 
# First create the prefix array
createPrefixArray(N, lines, size, pref)
 
# Print the total number of intersections
print(pointOfIntersection(M, segments, size, pref))
 
# This code is contributed by himanshu77




// C# implementation for the
// above approach.
using System;
 
class GFG{
 
// Function to create prefix sum array
static void createPrefixArray(int n, int []arr,
                              int prefSize,
                              int []pref)
{
     
    // Initialize the prefix array
    // to remove garbage values
    for(int i = 0; i < prefSize; i++)
    {
        pref[i] = 0;
    }
 
    // Marking the occurrences of
    // vertical lines
    for(int i = 0; i < n; i++)
    {
         
        // x is the value after
        // Index mapping
        int x = arr[i] + 1000000;
        pref[x]++;
    }
 
    // Creating the prefix array
    for(int i = 1; i < prefSize; i++)
    {
        pref[i] += pref[i - 1];
    }
}
 
// Function returns the count of
// total intersection
static int pointsOfIntersection(int m,
                                int [,]segments,
                                int size,
                                int []pref)
{
 
    // ans is the number of points of
    // intersection of the line segments
    // with the vertical lines
    int ans = 0;
 
    for(int i = 0; i < m; i++)
    {
        int x1 = segments[i, 0];
        int x2 = segments[i, 2];
 
        // Index mapping
        x1 = x1 + 1000000;
        x2 = x2 + 1000000;
 
        // We don't consider a vertical
        // line segment because even if
        // it falls on a vertical line
        // then it just touches it and
        // not intersects.
        if (x1 != x2)
        {
             
            // We have assumed that x1
            // will be left and x2 right
            // but if not then we just
            // swap them
            if (x1 > x2)
            {
                int temp = x1;
                x1 = x2;
                x2 = temp;
            }
 
            int Occ_Till_Right = pref[x2 - 1];
            int Occ_Till_Left = pref[x1];
 
            ans = ans + (Occ_Till_Right -
                         Occ_Till_Left);
        }
    }
    return ans;
}
 
// Driver code
public static void Main(String[] args)
{
 
    // N is the number of vertical lines
    // M is the number of line segments
    int N = 4;
    int M = 8;
 
    int size = 2000000 + 2;
    int []pref = new int[size];
 
    int []lines = { -5, -3, 2, 3 };
 
    // Format : x1, y1, x2, y1
    int [,]segments = { { -2, 5, 5, -6 },
                        { -5, -2, -3, -5 },
                        { -2, 3, -6, 1 },
                        { -1, -3, 4, 2 },
                        { 2, 5, 2, 1 },
                        { 4, 5, 4, -5 },
                        { -2, -4, 5, 3 },
                        { 1, 2, -2, 1 } };
 
    // First create the prefix array
    createPrefixArray(N, lines, size, pref);
 
    // Print the total number of intersections
    Console.Write(pointsOfIntersection(M, segments,
                                size, pref) + "\n");
}
}
 
// This code is contributed by Amit Katiyar




<script>
 
// JavaScript implementation of the
// above approach
 
// Function to create prefix sum array
function createPrefixArray(n, arr, prefSize, pref)
{
     
    // Initialize the prefix array
    // to remove garbage values
    for(let i = 0; i < prefSize; i++)
    {
        pref[i] = 0;
    }
 
    // Marking the occurrences of
    // vertical lines
    for(let i = 0; i < n; i++)
    {
         
        // x is the value after
        // Index mapping
        let x = arr[i] + 1000000;
        pref[x]++;
    }
 
    // Creating the prefix array
    for(let i = 1; i < prefSize; i++)
    {
        pref[i] += pref[i - 1];
    }
}
 
// Function returns the count of
// total intersection
function pointsOfIntersection(m, segments,
                              size, pref)
{
 
    // ans is the number of points of
    // intersection of the line segments
    // with the vertical lines
    let ans = 0;
 
    for(let i = 0; i < m; i++)
    {
        let x1 = segments[i][0];
        let x2 = segments[i][2];
 
        // Index mapping
        x1 = x1 + 1000000;
        x2 = x2 + 1000000;
 
        // We don't consider a vertical
        // line segment because even if
        // it falls on a vertical line
        // then it just touches it and
        // not intersects.
        if (x1 != x2)
        {
             
            // We have assumed that x1
            // will be left and x2 right
            // but if not then we just
            // swap them
            if (x1 > x2)
            {
                let temp = x1;
                x1 = x2;
                x2 = temp;
            }
 
            let Occ_Till_Right = pref[x2 - 1];
            let Occ_Till_Left = pref[x1];
 
            ans = ans + (Occ_Till_Right -
                         Occ_Till_Left);
        }
    }
    return ans;
}
     
// Driver Code
 
// N is the number of vertical lines
// M is the number of line segments
let N = 4;
let M = 8;
 
let size = 2000000 + 2;
let pref = Array.from({length: size}, (_, i) => 0);
let lines = [ -5, -3, 2, 3 ];
 
// Format : x1, y1, x2, y1
let segments = [ [ -2, 5, 5, -6 ],
                 [ -5, -2, -3, -5 ],
                 [ -2, 3, -6, 1 ],
                 [ -1, -3, 4, 2 ],
                 [ 2, 5, 2, 1 ],
                 [ 4, 5, 4, -5 ],
                 [ -2, -4, 5, 3 ],
                 [ 1, 2, -2, 1 ] ];
 
// First create the prefix array
createPrefixArray(N, lines, size, pref);
 
// Print the total number of intersections
document.write(pointsOfIntersection(M, segments,
                                   size, pref) + "\n");
                                    
// This code is contributed by sanjoy_62
           
</script>

Output: 
8

 

Approach 3: To optimize the above approach, we can adopt a space efficient method using Map Data structure. Follow the steps below to solve the problem:

Below is the implementation of the above approach.  




// C++ implementation for the
// above approach.
#include <bits/stdc++.h>
using namespace std;
 
// Function to create map that stores
// the number of occurrences of the
// vertical lines till now.
map<int, int> createMap(int n,
                        int arr[])
{
    map<int, int> mp;
 
    sort(arr, arr + n);
    for (int i = 0; i < n; i++) {
        mp.insert({ arr[i], i + 1 });
    }
    return mp;
}
 
// Function returns the count of
// total intersections
int pointsOfIntersection(int m,
                         int segments[][4],
                         int n,
                         map<int, int> pref)
{
    // ans stores the number
    // of intersections
    int ans = 0;
 
    // Loop over all the segments
    for (int i = 0; i < m; i++) {
        int x1 = segments[i][0];
        int x2 = segments[i][2];
        if (x1 == x2) {
            continue;
        }
 
        // For convenience we make x1 as
        // x co-ordinate of left point
        // and x2 as x co-ordinate of
        // right point.
        if (x1 > x2) {
            swap(x1, x2);
        }
 
        auto it1 = *pref.lower_bound(x1 + 1);
        auto it2 = *pref.upper_bound(x2 - 1);
 
        int intersections = 0;
 
        // If x co-ordinate of the left point
        // is after the last vertical line
        // then we dont add anything.
        if (pref.lower_bound(x1 + 1)
            == pref.end()) {
            intersections = 0;
        }
        // If there is no occurrence of any
        // vertical line after (x2-1)
        // then we can mark the
        // number of intersections as
        // n - occurrences till x1
        // because the total occurrences
        // are n and all of them
        // will fall before x2.
        else if (pref.upper_bound(x2 - 1)
                 == pref.end()) {
            intersections
                = n - it1.second + 1;
        }
        else {
            intersections
                = it2.second
                  - it1.second;
        }
        ans += intersections;
    }
    return ans;
}
 
// Driver code
int main()
{
    // N is the number of vertical lines
    // M is the number of line segments
    int N = 4;
    int M = 8;
 
    int lines[N] = { -5, -3, 2, 3 };
 
    // Format : x1, y1, x2, y1
    int segments[M][4]
        = { { -2, 5, 5, -6 },
            { -5, -2, -3, -5 },
            { -2, 3, -6, 1 },
            { -1, -3, 4, 2 },
            { 2, 5, 2, 1 },
            { 4, 5, 4, -5 },
            { -2, -4, 5, 3 },
            { 1, 2, -2, 1 } };
 
    map<int, int> pref = createMap(N, lines);
 
    cout << pointsOfIntersection(
                M,
                segments,
                N, pref)
         << endl;
    return 0;
}




// Java implementation for the
// above approach.
import java.util.*;
 
public class Main {
    private static TreeMap<Integer, Integer>
    createMap(int n, int[] arr)
    {
        // Function to create map that stores
        // the number of occurrences of the
        // vertical lines till now.
 
        TreeMap<Integer, Integer> pref = new TreeMap<>();
        Arrays.sort(arr); // sort the array
        int count = 0;
        for (int i = 0; i < n; i++) {
            pref.put(arr[i], ++count); // populate the map
        }
        return pref;
    }
 
    // Function returns the count of
    // total intersections
 
    private static int
    pointsOfIntersection(int m, int[][] segments, int n,
                         TreeMap<Integer, Integer> pref)
    {
 
        // ans stores the number
        // of intersections
        int ans = 0;
 
        // Loop over all the segments
        for (int i = 0; i < m; i++) {
            int x1 = segments[i][0];
            int x2 = segments[i][2];
            if (x1 == x2) {
                continue;
            }
 
            // For convenience we make x1 as
            // x co-ordinate of left point
            // and x2 as x co-ordinate of
            // right point.
            if (x1 > x2) {
                int temp = x1;
                x1 = x2;
                x2 = temp;
            }
 
            Map.Entry<Integer, Integer> it1
                = pref.ceilingEntry(x1 + 1);
            Map.Entry<Integer, Integer> it2
                = pref.floorEntry(x2 - 1);
 
            int intersections = 0;
 
            // If x co-ordinate of the left point
            // is after the last vertical line
            // then we dont add anything.
            if (it1 == null) {
                intersections = 0;
            }
 
            // If there is no occurrence of any
            // vertical line after (x2-1)
            // then we can mark the
            // number of intersections as
            // n - occurrences till x1
            // because the total occurrences
            // are n and all of them
            // will fall before x2
            else if (it2 == null) {
                intersections = n - it1.getValue() + 1;
            }
            else {
                intersections
                    = it2.getValue() - it1.getValue() + 1;
            }
            ans += intersections;
        }
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
 
        // N is the number of vertical lines
        // M is the number of line segments
        int N = 4;
        int M = 8;
 
        int[] lines = { -5, -3, 2, 3 };
 
        // Format : x1, y1, x2, y1
        int[][] segments
            = { { -2, 5, 5, -6 }, { -5, -2, -3, -5 },
                { -2, 3, -6, 1 }, { -1, -3, 4, 2 },
                { 2, 5, 2, 1 },   { 4, 5, 4, -5 },
                { -2, -4, 5, 3 }, { 1, 2, -2, 1 } };
 
        TreeMap<Integer, Integer> pref
            = createMap(N, lines);
 
        System.out.println(
            pointsOfIntersection(M, segments, N, pref));
    }
}




from typing import List, Tuple
from bisect import bisect_left, bisect_right
 
# Function to create map that stores
# the number of occurrences of the
# vertical lines till now.
def createMap(n: int, arr: List[int]) -> dict:
    mp = {}
    arr.sort()
    for i in range(n):
        mp[arr[i]] = i + 1
    return mp
 
# Function returns the count of
# total intersections
def pointsOfIntersection(m: int, segments: List[Tuple[int, int, int, int]], n: int, pref: dict) -> int:
    # ans stores the number
    # of intersections
    ans = 0
 
    # Loop over all the segments
    for i in range(m):
        x1, _, x2, _ = segments[i]
        if x1 == x2:
            continue
 
        # For convenience we make x1 as
        # x co-ordinate of left point
        # and x2 as x co-ordinate of
        # right point.
        if x1 > x2:
            x1, x2 = x2, x1
 
        it1 = bisect_left(list(pref.keys()), x1 + 1)
        it2 = bisect_right(list(pref.keys()), x2 - 1)
 
        intersections = 0
 
        # If x co-ordinate of the left point
        # is after the last vertical line
        # then we dont add anything.
        if it1 == len(pref):
            intersections = 0
        # If there is no occurrence of any
        # vertical line after (x2-1)
        # then we can mark the
        # number of intersections as
        # n - occurrences till x1
        # because the total occurrences
        # are n and all of them
        # will fall before x2.
        elif it2 == len(pref):
            intersections = n - pref[list(pref.keys())[it1]] + 1
        else:
            intersections = pref[list(pref.keys())[it2]] - pref[list(pref.keys())[it1]]
 
        ans += intersections
    return ans
 
# Driver code
if __name__ == "__main__":
    # N is the number of vertical lines
    # M is the number of line segments
    N = 4
    M = 8
 
    lines = [-5, -3, 2, 3]
 
    # Format : x1, y1, x2, y1
    segments = [(-2, 5, 5, -6),
                (-5, -2, -3, -5),
                (-2, 3, -6, 1),
                (-1, -3, 4, 2),
                (2, 5, 2, 1),
                (4, 5, 4, -5),
                (-2, -4, 5, 3),
                (1, 2, -2, 1)]
 
    pref = createMap(N, lines)
 
    print(pointsOfIntersection(M, segments, N, pref))




// C# Approach for the above problem
using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program{
      // function to create map that stores the number of occurrences
      // of the vertical lines till now.
    static SortedDictionary<int, int> createMap(int n, int[] arr){
        SortedDictionary<int, int> pref = new SortedDictionary<int, int>();
        Array.Sort(arr); // sort the array
        int count = 0;
        for (int i = 0; i < n; i++){
            pref[arr[i]] = ++count; // populate the map
        }
        return pref;
    }
 
      // function to count the total intersection
    static int pointsOfIntersection(int m, int[,] segments, int n, SortedDictionary<int, int> pref){
 
        // ans stores the number of intersections
        int ans = 0;
 
        // Loop over all the segments
        for (int i = 0; i < m; i++){
            int x1 = segments[i,0];
            int x2 = segments[i,2];
            if (x1 == x2){
                continue;
            }
            // For convenience we make x1 as
            // x co-ordinate of left point
            // and x2 as x co-ordinate of
            // right point.
            if (x1 > x2){
                int temp = x1;
                x1 = x2;
                x2 = temp;
            }
 
            var it1 = pref.FirstOrDefault(x => x.Key >= x1 + 1);
            var it2 = pref.LastOrDefault(x => x.Key <= x2 - 1);
 
            int intersections = 0;
            // If x co-ordinate of the left point
            // is after the last vertical line
            // then we dont add anything.
            if (it1.Key == 0 && it1.Value == 0){
                intersections = 0;
            }
           
            // If there is no occurrence of any
            // vertical line after (x2-1)
            // then we can mark the
            // number of intersections as
            // n - occurrences till x1
            // because the total occurrences
            // are n and all of them
            // will fall before x2
            else if (it2.Key == 0 && it2.Value == 0){
                intersections = n - it1.Value + 1;
            }
            else{
                intersections = it2.Value - it1.Value + 1;
            }
            ans += intersections;
        }
        return ans;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        // N is the number of vertical lines
        // M is the number of line segments
        int N = 4;
        int M = 8;
 
        int[] lines = { -5, -3, 2, 3 };
 
        // Format : x1, y1, x2, y1
        int[,] segments
            = { { -2, 5, 5, -6 }, { -5, -2, -3, -5 },
                { -2, 3, -6, 1 }, { -1, -3, 4, 2 },
                { 2, 5, 2, 1 },   { 4, 5, 4, -5 },
                { -2, -4, 5, 3 }, { 1, 2, -2, 1 } };
 
        SortedDictionary<int,int> pref=createMap(N , lines);
         
        Console.WriteLine(pointsOfIntersection(M ,segments ,N ,pref));
    }
}




// javascript implementation for the
// above approach.
 
// Function to create map that stores
// the number of occurrences of the
// vertical lines till now.
function createMap(n, arr)
{
    let mp = new Set();
    arr.sort();
 
    for (let i = 0; i < n; i++) {
        mp.add([arr[i], i+1].join(" "));
    }
     
    let res = [];
    for(let i of mp){
        let x = i.split(" ");
        res.push([parseInt(x[0]), parseInt(x[1])]);
    }
    res.sort(function(a,b){
        if(a[0] == b[0]) return a[1] - b[1];
        return a[0] - b[0];
    });
    return res;
}
 
function lower_bound(pref, x){
    let l = 0;
    let h = pref.length - 1;
     
    while(l <= h){
        let m = Math.floor((l + h) /2);
         
        if(pref[m][0] < x){
            l = m + 1;
        }
        else if(pref[m][0] == x){
            return m;
        }
        else{
            h = m - 1;
        }
    }
     
    return l;
}
 
function upper_bound(pref, x){
    let l = 0;
    let h = pref.length - 1;
     
    while(l <= h){
        let m = Math.floor((l + h)/2);
         
        if(pref[m][0] <= x){
            l = m + 1;
        }
        else{
            h = m - 1;
        }
    }
     
    return l;
}
 
// Function returns the count of
// total intersections
function pointsOfIntersection(m, segments, n, pref)
{
    // ans stores the number
    // of intersections
    let ans = 0;
 
    // Loop over all the segments
    for (let i = 0; i < m; i++) {
        let x1 = segments[i][0];
        let x2 = segments[i][2];
        if (x1 == x2) {
            continue;
        }
 
        // For convenience we make x1 as
        // x co-ordinate of left point
        // and x2 as x co-ordinate of
        // right point.
        if (x1 > x2) {
            let temp = x1;
            x1 = x2;
            x2 = temp;
        }
 
        let it1 = lower_bound(pref, x1 + 1);
        let it2 = upper_bound(pref, x2 - 1);
 
        let intersections = 0;
 
        // If x co-ordinate of the left point
        // is after the last vertical line
        // then we dont add anything.
        if(it1 == pref.length){
            intersections = 0;
        }
        // If there is no occurrence of any
        // vertical line after (x2-1)
        // then we can mark the
        // number of intersections as
        // n - occurrences till x1
        // because the total occurrences
        // are n and all of them
        // will fall before x2.
        else if(it2 == pref.length){
            intersections = n - pref[it1][1] + 1;
        }
        else {
            intersections = pref[it2][1] - pref[it1][1];
        }
        ans += intersections;
    }
    return ans;
}
 
// Driver code
// N is the number of vertical lines
// M is the number of line segments
let N = 4;
let M = 8;
 
let lines = [ -5, -3, 2, 3 ];
 
// Format : x1, y1, x2, y1
let segments
    = [[ -2, 5, 5, -6 ],
        [ -5, -2, -3, -5 ],
        [ -2, 3, -6, 1 ],
        [ -1, -3, 4, 2 ],
        [ 2, 5, 2, 1 ],
        [ 4, 5, 4, -5 ],
        [ -2, -4, 5, 3 ],
        [ 1, 2, -2, 1 ] ];
 
let pref = createMap(N, lines);
 
console.log(pointsOfIntersection(M, segments, N, pref) + 1);
 
// The code is contributed by Nidhi goel.

Output: 
8

 


Article Tags :