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: 1Â
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: 8Â
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:Â
- The first observation we can make is that the y-coordinates do not matter. Also, we can observe that just touching the vertical line does not count as an intersection.
- First, compute a prefix array of the number of occurrences of vertical lines till now and then just subtract the number of occurrences till x2-1 (we don’t consider x2 as it just qualifies as touch and not as an intersection) from the number of occurrences till x1. So for each segment, computational complexity reduces to O(1).
Below is the implementation of the above approach.Â
C++
// C++ implementation for the// above approach.#include <bits/stdc++.h>using namespace std;Â
// Function to create prefix sum arrayvoid 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 intersectionint 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
// Java implementation for the// above approach.import java.util.*;Â
class GFG{Â
// Function to create prefix sum arraystatic 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 intersectionstatic 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 codepublic 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
# Python3 implementation for the # above approachÂ
# Function to create prefix sum arraydef 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 intersectiondef 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 linesN = 4Â
# Number of line segmentsM = 8Â
size = 2000000 + 2pref = [0] * size lines = [ -5, -3, 2, 3 ]Â
# Format : x1, y1, x2, y2segments = [ [ -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 arraycreatePrefixArray(N, lines, size, pref)Â
# Print the total number of intersectionsprint(pointOfIntersection(M, segments, size, pref))Â
# This code is contributed by himanshu77 |
C#
// C# implementation for the// above approach.using System;Â
class GFG{Â
// Function to create prefix sum arraystatic 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 intersectionstatic 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 codepublic 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 |
Javascript
<script>Â
// JavaScript implementation of the// above approachÂ
// Function to create prefix sum arrayfunction 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 intersectionfunction 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 segmentslet 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, y1let 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 arraycreatePrefixArray(N, lines, size, pref);Â
// Print the total number of intersectionsdocument.write(pointsOfIntersection(M, segments,                                   size, pref) + "\n");                                    // This code is contributed by sanjoy_62           </script> |
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:
- We can make a map which stores the number of occurrences till now, just with the difference from the first approach is that we insert only the co-ordinates that have the vertical lines.
- When we want to search the number of intersections from x1 to x2, we can just subtract lower_bound(x1+1) from upper_bound(x2-1) of the map.
Below is the implementation of the above approach. Â
C++
// 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 intersectionsint 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 codeint 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
// 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));    }} |
Python3
from typing import List, Tuplefrom 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 intersectionsdef 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 codeif __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#
// C# Approach for the above problemusing 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
// 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 intersectionsfunction 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 segmentslet N = 4;let M = 8;Â
let lines = [ -5, -3, 2, 3 ];Â
// Format : x1, y1, x2, y1let 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. |
8
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!




