Robot Factory (Codeforces 1600J)
Tags: Others, bitmasks

You have received data from a Bubble bot. You know your task is to make factory facilities, but before you even start, you need to know how big the factory is and how many rooms it has. When you look at the data you see that you have the dimensions of the construction, which is in rectangle shape: N x M. Then in the next N lines you have M numbers. These numbers represent factory tiles and they can go from 0 to 15. Each of these numbers should be looked in its binary form. Because from each number you know on which side the tile has walls. For example number 10 in it's binary form is 1010, which means that it has a wall from the North side, it doesn't have a wall from the East, it has a wall on the South side and it doesn't have a wall on the West side. So it goes North, East, South, West. It is guaranteed that the construction always has walls on it's edges. The input will be correct. Your task is to print the size of the rooms from biggest to smallest. 

Input: The first line has two numbers which are N and M, the size of the construction. Both are integers: $$$n$$$ ($$$1 \leq n \leq 10^3$$$)$$$m$$$ ($$$1 \leq m \leq 10^3$$$)Next N x M numbers represent each tile of construction.

Output: Once you finish processing the data your output consists of one line sorted from biggest to smallest room sizes. 


Sample Inputs:
4 5
9 14 11 12 13
5 15 11 6 7
5 9 14 9 14
3 2 14 3 14

Sample Outputs:
9 4 4 2 1

Solution (Python):
import sys
sys.setrecursionlimit(100000)

def _r():
    return sys.stdin.buffer.readline()

def rs():
    return _r().decode('ascii').strip()

def rn():
    return int(_r())

def rnt():
    return map(int, _r().split())

def rnl():
    return list(rnt())

def solve(n, m, mat):
    (dp, color) = ([[0] * m for _ in range(n)], 1)

    def _color(r, c, color):
        (stack, colored) = ([(r, c)], 1)
        dp[r][c] = color
        while stack:
            (r, c) = stack.pop()
            for (dr, dc, mask) in ((-1, 0, 8), (0, 1, 4), (1, 0, 2), (0, -1, 1)):
                (nr, nc) = (r + dr, c + dc)
                if mat[r][c] & mask == 0 and dp[nr][nc] == 0:
                    dp[nr][nc] = color
                    colored += 1
                    stack.append((nr, nc))
        return colored
    sol = []
    for r in range(n):
        for c in range(m):
            if dp[r][c] == 0:
                sol.append(_color(r, c, color))
                color += 1
    return sorted(sol, reverse=True)
(n, m) = rnt()
mat = []
for _ in range(n):
    mat.append(rnl())
print(' '.join(map(str, solve(n, m, mat))), '')

Solution (Python):
def naiveSolve():
    return

def solve():
    return

class UnionFind:

    def __init__(self, n):
        self.parent = list(range(n))

    def find(self, a):
        acopy = a
        while a != self.parent[a]:
            a = self.parent[a]
        while acopy != a:
            (self.parent[acopy], acopy) = (a, self.parent[acopy])
        return a

    def union(self, a, b):
        self.parent[self.find(b)] = self.find(a)

def northWall(x):
    return x & 8 > 0

def eastWall(x):
    return x & 4 > 0

def southWall(x):
    return x & 2 > 0

def westWall(x):
    return x & 1 > 0

def main():
    (n, m) = readIntArr()
    grid = []
    for _ in range(n):
        grid.append(readIntArr())
    uf = UnionFind(n * m)
    for i in range(n):
        for j in range(m):
            if j + 1 < m and eastWall(grid[i][j]) == westWall(grid[i][j + 1]) == False:
                uf.union(i * m + j, i * m + j + 1)
            if i + 1 < n and southWall(grid[i][j]) == northWall(grid[i + 1][j]) == False:
                uf.union(i * m + j, (i + 1) * m + j)
    sz = [False] * (n * m)
    for i in range(n):
        for j in range(m):
            sz[uf.find(i * m + j)] += 1
    rooms = []
    for x in range(n * m):
        if sz[x] > 0:
            rooms.append(sz[x])
    rooms.sort(reverse=True)
    oneLineArrayPrint(rooms)
    return
import sys
input = sys.stdin.buffer.readline

def oneLineArrayPrint(arr):
    print(' '.join([str(x) for x in arr]) + ' ')

def multiLineArrayPrint(arr):
    print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
    print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
    return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
    dv = defaultValFactory
    da = dimensionArr
    if len(da) == 1:
        return [dv() for _ in range(da[0])]
    else:
        return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(x):
    print('{}'.format(x))
    sys.stdout.flush()
    return int(input())

def answerInteractive(ans):
    print('! {}'.format(ans))
    sys.stdout.flush()
inf = float('inf')
from math import gcd, floor, ceil
for _abc in range(1):
    main()

Solution (Python):
from audioop import reverse
import io, os, sys
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def solve():
    (n, m) = map(int, input().split())
    edges = [[set() for _ in range(m)] for _ in range(n)]
    board = []
    for i in range(n):
        board.append(list(map(int, input().split())))
    ans = []
    queue = []
    edge_map = [[1, (0, -1)], [2, (1, 0)], [4, (0, 1)], [8, (-1, 0)]]
    for i in range(n):
        for j in range(m):
            if board[i][j] != -1:
                queue.append((i, j))
                ans.append(0)
            while queue:
                (ii, jj) = queue.pop()
                w = board[ii][jj]
                if w == -1:
                    continue
                board[ii][jj] = -1
                ans[-1] += 1
                for v in edge_map:
                    if w & v[0] == 0 and board[ii + v[1][0]][jj + v[1][1]] != -1:
                        queue.append((ii + v[1][0], jj + v[1][1]))
    ans.sort(reverse=True)
    l = len(ans)
    for i in range(l):
        sys.stdout.write(f'{ans[i]} ')
if __name__ == '__main__':
    solve()