Rectangle Shrinking (Codeforces 1781E)
Tags: Greedy, two pointers

You have a rectangular grid of height $$$2$$$ and width $$$10^9$$$ consisting of unit cells. There are $$$n$$$ rectangles placed on this grid, and the borders of these rectangles pass along cell borders. The $$$i$$$-th rectangle covers all cells in rows from $$$u_i$$$ to $$$d_i$$$ inclusive and columns from $$$l_i$$$ to $$$r_i$$$ inclusive ($$$1 \le u_i \le d_i \le 2$$$; $$$1 \le l_i \le r_i \le 10^9$$$). The initial rectangles can intersect, be nested, and coincide arbitrarily.You should either remove each rectangle, or replace it with any of its non-empty subrectangles. In the latter case, the new subrectangle must lie inside the initial rectangle, and its borders must still pass along cell borders. In particular, it is allowed for the subrectangle to be equal to the initial rectangle.After that replacement, no two (non-removed) rectangles are allowed to have common cells, and the total area covered with the new rectangles must be as large as possible.  Illustration for the first test case. The initial rectangles are given at the top, the new rectangles are given at the bottom. Rectangle number $$$4$$$ is removed. 

Input: Each test contains multiple test cases. The first line contains the number of test cases $$$t$$$ ($$$1 \le t \le 10^4$$$). The description of the test cases follows.The first line of each test case contains a single integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — the number of rectangles.Each of the next $$$n$$$ lines contains four integers $$$u_i, l_i, d_i, r_i$$$ ($$$1 \le u_i \le d_i \le 2$$$; $$$1 \le l_i \le r_i \le 10^9$$$) — the coordinates of cells located in the top-left and the bottom-right corners of the rectangle, respectively.It is guaranteed that the sum of $$$n$$$ over all test cases does not exceed $$$2 \cdot 10^5$$$.

Output: For each test case, first print an integer $$$s$$$ — the largest possible covered by new rectangles area. Then print $$$n$$$ lines with your solution to cover this area.In the $$$i$$$-th of these lines print four integers $$$u'_i, l'_i, d'_i, r'_i$$$. If you remove the $$$i$$$-th rectangle, print $$$u'_i = l'_i = d'_i = r'_i = 0$$$. Otherwise, these numbers denote the new coordinates of the top-left and the bottom-right corners of the $$$i$$$-th rectangle, satisfying $$$u_i \le u'_i \le d'_i \le d_i$$$; $$$l_i \le l'_i \le r'_i \le r_i$$$.If there are multiple solutions, print any.

Note: The picture in the statement illustrates the first test case.

Sample Inputs:
8
5
1 2 2 4
2 4 2 8
1 4 2 7
1 2 1 2
1 9 1 10
2
1 1 1 10
1 5 1 15
2
1 1 1 10
1 1 1 10
5
1 3 1 7
1 3 1 8
1 1 1 4
1 2 1 7
1 10 1 11
2
1 1 2 10
1 5 1 8
2
1 5 2 10
1 2 1 7
2
1 5 2 10
2 2 2 15
5
2 6 2 7
1 4 2 5
1 5 1 9
1 7 2 10
1 2 1 6

Sample Outputs:
15
1 2 2 4
2 5 2 8
1 5 1 7
0 0 0 0
1 9 1 10
15
1 1 1 10
1 11 1 15
10
1 1 1 10
0 0 0 0
10
0 0 0 0
1 8 1 8
1 1 1 4
1 5 1 7
1 10 1 11
20
1 1 2 10
0 0 0 0
15
1 5 2 10
1 2 1 4
20
1 5 1 10
2 2 2 15
16
2 6 2 6
2 4 2 5
0 0 0 0
1 7 2 10
1 2 1 6

Solution (Python):
def add(heap, x):
    heap.append(x)
    i = len(heap) - 1
    while i and heap[(i - 1) // 2][2] > heap[i][2]:
        (heap[(i - 1) // 2], heap[i]) = (heap[i], heap[(i - 1) // 2])
        i = (i - 1) // 2
    return heap

def get(heap):
    return heap[0]

def pop(heap):
    heap[0] = heap[len(heap) - 1]
    heap.pop()
    i = 0
    while 2 * i + 2 < len(heap):
        x = 2 * i + 1
        y = 2 * i + 2
        a = heap[x][2] < heap[i][2]
        b = heap[y][2] < heap[i][2]
        if a and b:
            if heap[x][2] < heap[y][2]:
                (heap[x], heap[i]) = (heap[i], heap[x])
                i = x
            else:
                (heap[y], heap[i]) = (heap[i], heap[y])
                i = y
        elif a:
            (heap[x], heap[i]) = (heap[i], heap[x])
            i = x
        elif b:
            (heap[y], heap[i]) = (heap[i], heap[y])
            i = y
        else:
            break
    if 2 * i + 1 < len(heap):
        x = 2 * i + 1
        a = heap[x][2] < heap[i][2]
        if a:
            (heap[x], heap[i]) = (heap[i], heap[x])
            i = x
    return heap
t = int(input())
for q in range(t):
    l = [[], [], []]
    n = int(input())
    rect = []
    for i in range(n):
        (r1, c1, r2, c2) = map(int, input().split())
        rect.append([i, r1 - 1, c1 - 1, r2 - 1, c2 - 1])
    rect = sorted(rect, key=lambda x: x[2])
    p = [0 - 1, -1]
    ans = []
    heap = []
    for i in rect:
        if i[1] == i[3]:
            if i[4] <= p[i[1]]:
                i = [i[0], -1, -1, -1, -1]
            elif i[2] <= p[i[1]]:
                i[2] = p[i[1]] + 1
                p[i[1]] = i[4]
            else:
                p[i[1]] = i[4]
            heap = add(heap, i)
        elif i[4] <= p[0]:
            i[1] = 1
            if i[1] == i[3]:
                if i[4] <= p[i[1]]:
                    i = [i[0], -1, -1, -1, -1]
                elif i[2] <= p[i[1]]:
                    i[2] = p[i[1]] + 1
                    p[i[1]] = i[4]
                else:
                    p[i[1]] = i[4]
                heap = add(heap, i)
        elif i[4] <= p[1]:
            i[3] = 0
            if i[1] == i[3]:
                if i[4] <= p[i[1]]:
                    i = [i[0], -1, -1, -1, -1]
                elif i[2] <= p[i[1]]:
                    i[2] = p[i[1]] + 1
                    p[i[1]] = i[4]
                else:
                    p[i[1]] = i[4]
                heap = add(heap, i)
        else:
            while len(heap) > 0 and get(heap)[2] < i[4]:
                x = get(heap)
                if x[2] >= i[2]:
                    x = [x[0], -1, -1, -1, -1]
                else:
                    x[4] = min(x[4], i[2] - 1)
                ans.append(x)
                heap = pop(heap)
            p[0] = i[4]
            p[1] = i[4]
            heap = add(heap, i)
    for i in heap:
        ans.append(i)
    ans = sorted(ans, key=lambda x: x[0])
    s = 0
    for i in ans:
        if i[1] != -1:
            s += (i[3] - i[1] + 1) * (i[4] - i[2] + 1)
    print(s)
    for i in ans:
        print(i[1] + 1, i[2] + 1, i[3] + 1, i[4] + 1)

Solution (Python):
import sys
input = sys.stdin.buffer.readline
for _ in range(int(input())):
    n = int(input())
    rec = [list(map(int, input().split())) for _ in range(n)]
    rec1 = [[], []]
    rec2 = []
    for (i, re) in enumerate(rec):
        (u, l, d, r) = re
        if u == d:
            rec1[u - 1].append([l, r, i])
        else:
            rec2.append((l, r, i))
    for i in range(2):
        remove = [0] * len(rec1[i])
        rec1[i].sort()
        e = 0
        for j in range(len(rec1[i])):
            (l, r, idx) = rec1[i][j]
            if l <= e:
                if r > e:
                    rec1[i][j][0] = e + 1
                    rec[idx][1] = e + 1
                else:
                    remove[j] = 1
                    rec[idx] = [0] * 4
            e = max(e, r)
        rec1[i] = [rec1[i][j] for j in range(len(rec1[i])) if not remove[j]]
    rec2.sort()
    e = 0
    for (l, r, i) in rec2:
        if l <= e:
            if r > e:
                rec[i][1] = e + 1
            else:
                rec[i] = [0] * 4
        e = max(e, r)
    for i in range(2):
        if not rec1[i]:
            continue
        s = 0
        for (_, _, idx) in rec2:
            if rec[idx] != [0] * 4:
                (u, l, d, r) = rec[idx]
                while s + 1 < len(rec1[i]) and rec1[i][s][1] < l:
                    s += 1
                if rec1[i][s][1] < l:
                    break
                gap = False
                e = s
                while e + 1 < len(rec1[i]) and rec1[i][e][1] < r:
                    if rec1[i][e][1] + 1 != rec1[i][e + 1][0]:
                        gap = True
                    e += 1
                if rec1[i][s][0] > l or rec1[i][e][1] < r:
                    gap = True
                if gap:
                    for j in range(s, e + 1):
                        (l2, r2, idx) = rec1[i][j]
                        if l <= l2 and r2 <= r:
                            rec[idx] = [0] * 4
                        elif l2 < l:
                            rec[idx][3] = l - 1
                        elif l2 <= r < r2:
                            rec1[i][j][0] = r + 1
                            rec[idx][1] = r + 1
                elif i == 0:
                    rec[idx][0] += 1
                else:
                    rec[idx][2] -= 1
                    if rec[idx][0] > rec[idx][2]:
                        rec[idx] = [0] * 4
                s = e
    area = 0
    for (u, l, d, r) in rec:
        if u:
            area += (d - u + 1) * (r - l + 1)
    print(area)
    for re in rec:
        sys.stdout.write(' '.join(map(str, re)) + '\n')

Solution (Python):
import sys
input = sys.stdin.buffer.readline
for _ in range(int(input())):
    n = int(input())
    rec = [list(map(int, input().split())) for _ in range(n)]
    rec1 = [[], []]
    rec2 = []
    for (i, re) in enumerate(rec):
        (u, l, d, r) = re
        if u == d:
            rec1[u - 1].append([l, r, i])
        else:
            rec2.append((l, r, i))
    for i in range(2):
        remove = [0] * len(rec1[i])
        rec1[i].sort()
        e = 0
        for j in range(len(rec1[i])):
            (l, r, idx) = rec1[i][j]
            if l <= e:
                if r > e:
                    rec1[i][j][0] = e + 1
                    rec[idx][1] = e + 1
                else:
                    remove[j] = 1
                    rec[idx] = [0] * 4
            e = max(e, r)
        rec1[i] = [rec1[i][j] for j in range(len(rec1[i])) if not remove[j]]
    rec2.sort()
    e = 0
    for (l, r, i) in rec2:
        if l <= e:
            if r > e:
                rec[i][1] = e + 1
            else:
                rec[i] = [0] * 4
        e = max(e, r)
    for i in range(2):
        if not rec1[i]:
            continue
        s = 0
        for (_, _, idx) in rec2:
            if rec[idx] != [0] * 4:
                (u, l, d, r) = rec[idx]
                while s + 1 < len(rec1[i]) and rec1[i][s][1] < l:
                    s += 1
                if rec1[i][s][1] < l:
                    break
                gap = False
                e = s
                while e + 1 < len(rec1[i]) and rec1[i][e][1] < r:
                    if rec1[i][e][1] + 1 != rec1[i][e + 1][0]:
                        gap = True
                    e += 1
                if rec1[i][s][0] > l or rec1[i][e][1] < r:
                    gap = True
                if gap:
                    for j in range(s, e + 1):
                        (l2, r2, idx) = rec1[i][j]
                        if l <= l2 and r2 <= r:
                            rec[idx] = [0] * 4
                        elif l2 < l:
                            rec[idx][3] = l - 1
                        elif l2 <= r < r2:
                            rec1[i][j][0] = r + 1
                            rec[idx][1] = r + 1
                elif i == 0:
                    rec[idx][0] += 1
                else:
                    rec[idx][2] -= 1
                    if rec[idx][0] > rec[idx][2]:
                        rec[idx] = [0] * 4
                s = e
    area = 0
    for (u, l, d, r) in rec:
        if u:
            area += (d - u + 1) * (r - l + 1)
    print(area)
    for re in rec:
        print(*re)