You are given a 2D integer array rectangles where rectangles[i] = [li, hi] indicates that ith rectangle has a length of li and a height of hi. You are also given a 2D integer array points where points[j] = [xj, yj] is a point with coordinates (xj, yj).

The ith rectangle has its bottom-left corner point at the coordinates (0, 0) and its top-right corner point at (li, hi).

Return an integer array count of length points.length where count[j] is the number of rectangles that contain the jth point.

The ith rectangle contains the jth point if 0 &lt;= xj &lt;= li and 0 &lt;= yj &lt;= hi. Note that points that lie on the edges of a rectangle are also considered to be contained by that rectangle.

&nbsp;
Example 1:

Input: rectangles = [[1,2],[2,3],[2,5]], points = [[2,1],[1,4]]
Output: [2,1]
Explanation: 
The first rectangle contains no points.
The second rectangle contains only the point (2, 1).
The third rectangle contains the points (2, 1) and (1, 4).
The number of rectangles that contain the point (2, 1) is 2.
The number of rectangles that contain the point (1, 4) is 1.
Therefore, we return [2, 1].


Example 2:

Input: rectangles = [[1,1],[2,2],[3,3]], points = [[1,3],[1,1]]
Output: [1,3]
Explanation:
The first rectangle contains only the point (1, 1).
The second rectangle contains only the point (1, 1).
The third rectangle contains the points (1, 3) and (1, 1).
The number of rectangles that contain the point (1, 3) is 1.
The number of rectangles that contain the point (1, 1) is 3.
Therefore, we return [1, 3].


&nbsp;
Constraints:


	1 &lt;= rectangles.length, points.length &lt;= 5 * 104
	rectangles[i].length == points[j].length == 2
	1 &lt;= li, xj &lt;= 109
	1 &lt;= hi, yj &lt;= 100
	All the rectangles are unique.
	All the points are unique.


class Solution:
    def binarySearch(self, arr, target):
        left, right = 0, len(arr)
        ans = None
        while left < right:
            mid = left + ((right-left)//2)
            if arr[mid] >= target:
                # Potential answer found! Now try to minimize it iff possible.
                ans = mid
                right = mid
            else:
                left = mid + 1
        return ans
        
    def countRectangles(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]:
        # Sort rectangles based on the lengths
        rectangles.sort()  
        # Group rectangles by their height in increasing order of their length
        lengths = {}
        for x,y in rectangles:
            if y in lengths:
                lengths[y].append(x)
            else:
                lengths[y] = [x]
        
        heights = sorted(list(lengths.keys()))
        
        count = [0] * len(points)
        
        for idx, point in enumerate(points):
            x, y = point
            # Get the  min height rectangle that would accommodate the y coordinate of current point.
            minHeightRectIdx = self.binarySearch(heights, y)
            if minHeightRectIdx is not None:
                for h in heights[minHeightRectIdx:]:
                    # Get the Min length rectangle that would accommodate the x coordinate of current point for all h height rectangles.
                    minLenRectIdx = self.binarySearch(lengths[h], x)
                    if minLenRectIdx is not None:
                        count[idx] += len(lengths[h]) - minLenRectIdx
        
        return count
class Solution {
    public int[] countRectangles(int[][] rectangles, int[][] points) {
        int max = Integer.MIN_VALUE;

        TreeMap<Integer, List<Integer>> rects = new TreeMap<>();
        for(int[] rect : rectangles) {
            if (!rects.containsKey(rect[1])) {
                rects.put(rect[1], new ArrayList<Integer>());
            }

            rects.get(rect[1]).add(rect[0]);
            max = Math.max(max, rect[1]);
        }

        for(int k : rects.keySet()) {
            Collections.sort(rects.get(k));
        }

        int[] ans = new int[points.length];
        for(int i = 0; i < points.length; i++) {
            if (points[i][1] > max) {
                continue;
            }

            int count = 0;

            for(int key : rects.subMap(points[i][1], max + 1).keySet()) {
                List<Integer> y = rects.get(key);

                count += binarySearch(y, points[i][0]);
            }

            ans[i] = count;
        }

        return ans;
    }

    private int binarySearch(List<Integer> vals, int val) {
        int lo = 0;
        int hi = vals.size() - 1;
        int id = -1;

        while(lo <= hi) {
            int mid = lo + (hi - lo) / 2;

            if (vals.get(mid) < val) {
                lo = mid + 1;
            } else {
                id = mid;
                hi = mid - 1;
            }
        }

        if (id < 0) {
            return 0;
        }

        return vals.size() - id;
    }
}
class Solution {
public:
    vector<int> countRectangles(vector<vector<int>>& rectangles, vector<vector<int>>& points) {
        
        int i, count, ind, x, y, n = rectangles.size();
        
        vector<int> ans;
        vector<vector<int>> heights(101);
        
        for(auto rect : rectangles)
            heights[rect[1]].push_back(rect[0]);
        
        for(i=0;i<101;i++)
            sort(heights[i].begin(), heights[i].end());
        
        for(auto point : points)
        {
            count = 0;
            x = point[0];
            y = point[1];
            for(i=y;i<101;i++)
            {
                ind = lower_bound(heights[i].begin(), heights[i].end(), x) - heights[i].begin();
                count += (heights[i].size() - ind);
            }
            ans.push_back(count);
        }
        return ans;
    }
};
var countRectangles = function(rectangles, points) {
  let buckets = Array(101).fill(0).map(() => []);
  for (let [x, y] of rectangles) {
    buckets[y].push(x);
  }
  for (let i = 0; i < 101; i++) buckets[i].sort((a, b) => a - b);

  let res = [];
  for (let point of points) {
    let sum = 0;
    for (let j = point[1]; j < 101; j++) {
      // lowest index >= point[0]
      let index = lower_bound(buckets[j], point[0]);
      sum += buckets[j].length - index;
    }
    res.push(sum);
  }
  return res;

  function lower_bound(arr, targ) {
    let low = 0, high = arr.length;
    while (low < high) {
      let mid = Math.floor((low + high) / 2);
      if (arr[mid] >= targ) high = mid;
      else low = mid + 1;
    }
    return low;
  }
};
Count Number of Rectangles Containing Each Point