<p>You are given a 2D integer array <code>intervals</code>, where <code>intervals[i] = [left<sub>i</sub>, right<sub>i</sub>]</code> describes the <code>i<sup>th</sup></code> interval starting at <code>left<sub>i</sub></code> and ending at <code>right<sub>i</sub></code> <strong>(inclusive)</strong>. The <strong>size</strong> of an interval is defined as the number of integers it contains, or more formally <code>right<sub>i</sub> - left<sub>i</sub> + 1</code>.</p>

<p>You are also given an integer array <code>queries</code>. The answer to the <code>j<sup>th</sup></code> query is the <strong>size of the smallest interval</strong> <code>i</code> such that <code>left<sub>i</sub> &lt;= queries[j] &lt;= right<sub>i</sub></code>. If no such interval exists, the answer is <code>-1</code>.</p>

<p>Return <em>an array containing the answers to the queries</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> intervals = [[1,4],[2,4],[3,6],[4,4]], queries = [2,3,4,5]
<strong>Output:</strong> [3,3,1,4]
<strong>Explanation:</strong> The queries are processed as follows:
- Query = 2: The interval [2,4] is the smallest interval containing 2. The answer is 4 - 2 + 1 = 3.
- Query = 3: The interval [2,4] is the smallest interval containing 3. The answer is 4 - 2 + 1 = 3.
- Query = 4: The interval [4,4] is the smallest interval containing 4. The answer is 4 - 4 + 1 = 1.
- Query = 5: The interval [3,6] is the smallest interval containing 5. The answer is 6 - 3 + 1 = 4.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> intervals = [[2,3],[2,5],[1,8],[20,25]], queries = [2,19,5,22]
<strong>Output:</strong> [2,-1,4,6]
<strong>Explanation:</strong> The queries are processed as follows:
- Query = 2: The interval [2,3] is the smallest interval containing 2. The answer is 3 - 2 + 1 = 2.
- Query = 19: None of the intervals contain 19. The answer is -1.
- Query = 5: The interval [2,5] is the smallest interval containing 5. The answer is 5 - 2 + 1 = 4.
- Query = 22: The interval [20,25] is the smallest interval containing 22. The answer is 25 - 20 + 1 = 6.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= intervals.length &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= queries.length &lt;= 10<sup>5</sup></code></li>
	<li><code>intervals[i].length == 2</code></li>
	<li><code>1 &lt;= left<sub>i</sub> &lt;= right<sub>i</sub> &lt;= 10<sup>7</sup></code></li>
	<li><code>1 &lt;= queries[j] &lt;= 10<sup>7</sup></code></li>
</ul>

import bisect
from sortedcontainers import SortedList

class Solution:
    def get_unique_coords(self, intervals):
        coords = []
        for start, end in intervals:
            coords.append(start-1)
            coords.append(start)
            coords.append(end)
            coords.append(end+1)
        coords.sort()
        cnt = 0
        for c in coords:
            if cnt == 0 or c != coords[cnt-1]:
                coords[cnt] = c
                cnt += 1
        del coords[cnt:]
        return coords


    def minInterval(self, intervals: List[List[int]], queries: List[int]) -> List[int]:
        coords = self.get_unique_coords(intervals)
        def get_index(coord):
            index = min(bisect.bisect_left(coords, coord), len(coords) - 1)
            return index

        size = 2
        while size < len(coords):
            size *= 2
        tree = [-1] * (size + len(coords))
        def tree_add(i, l, r, interval, value):
            m = (l + r) // 2
            if interval[0] <= l and interval[1] >= r:
                tree[i] = min(tree[i], value) if tree[i] != -1 else value
                return
            if interval[0] <= m:
                tree_add(2 * i, l, m, interval, value)
            if interval[1] >= m + 1:
                tree_add(2 * i + 1, m + 1, r, interval, value)

        def tree_query(i, l, r, query):
            assert query >= l and query <= r
            if l == r:
                return tree[i]
            m = (l + r) // 2
            if query <= m:
                other = tree_query(2*i, l, m, query)
            else:
                other = tree_query(2*i+1, m+1, r, query)
            if other != -1 and tree[i] != -1:
                return min(tree[i], other)
            elif other != -1:
                return other
            else:
                return tree[i]

        for interval in intervals:
            c0, c1 = get_index(interval[0]), get_index(interval[1])
            tree_add(1, 0, size-1, [c0, c1], interval[1] - interval[0] + 1)

        result = []
        for q in queries:
            c = get_index(q)
            result.append(tree_query(1, 0, size-1, c))
        return result


# class Solution:
#     def minInterval(self, intervals: List[List[int]], queries: List[int]) -> List[int]:
#         result = [-1] * len(queries)
#         queries = sorted([(q, i) for (i, q) in enumerate(queries)])

#         events = []
#         for start, end in intervals:
#             events.append((start, (True, start, end)))
#             events.append((end+1, (False, start, end)))
#         events = sorted(events)
#         next_event = 0

#         current = SortedList()
#         for q, i in queries:
#             while next_event < len(events) and events[next_event][0] <= q:
#                 _, (is_start, start, end) = events[next_event]
#                 if is_start:
#                     current.add(end-start+1)
#                 else:
#                     current.remove(end-start+1)
#                 next_event += 1

#             if len(current) > 0:
#                 result[i] = current[0]
#         return result

65532