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))