# A. Time Needed to Buy Tickets (opens new window)

Count the total time spent by peoples before people k and after people k.

DETAILS
def timeRequiredToBuy(self, tickets: List[int], k: int) -> int:
        ans, a = 0, tickets[k]
        for t in tickets[:k]:
            ans += min(t, a)
        for t in tickets[k + 1:]:
            ans += min(t, a - 1)
        return ans + a

# B. Reverse Nodes in Even Length Groups (opens new window)

Classic reverse node.

DETAILS
def reverseEvenLengthGroups(self, head: Optional[ListNode]) -> Optional[ListNode]:
        prev = head
        d = 2 
        while prev.next:
            node, n = prev, 0
            for _ in range(d):
                if not node.next:
                    break
                n += 1
                node = node.next
            if n & 1:  # odd length
                prev = node
            else:      # even length
                node, rev = prev.next, None
                for _ in range(n):
                    node.next, node, rev = rev, node.next, node
                prev.next.next, prev.next, prev = node, rev, prev.next
            d += 1
        return head

# C. Decode the Slanted Ciphertext (opens new window)

DETAILS
def decodeCiphertext(self, A: str, rows: int) -> str:
        res = []
        n = math.ceil(len(A) / rows)
        for i in range(rows):
            res.append(A[i * n:(i + 1) * n])
        res[-1] = res[-1] + " "*(n - len(res[-1]))
        ans = ""
        i, j = 0, 0
        ti = 0
        while ti < n:
            while i < n and j < rows:
                ans += res[j][i]
                i += 1
                j += 1
            ti += 1
            i = ti
            j = 0
        aa = ans.rstrip()
        return aa

# D. Process Restricted Friend Requests (opens new window)

DSU

DETAILS
def friendRequests(self, n: int, R: List[List[int]], Q: List[List[int]]) -> List[bool]:
        root = list(range(n))
        def find(x):
            if x != root[x]: root[x] = find(root[x])
            return root[x]
        def union(x, y):
            a, b = find(x), find(y)
            if a != b: root[a] = b
            setd[b] |= setd[a]
            outer[b] |= outer[a]
        resd = collections.defaultdict(set)
        outer = collections.defaultdict(set)
        for a, b in R:
            resd[a].add(b)
            resd[b].add(a)
            outer[a].add(b)
            outer[b].add(a)
        ans = []
        setd = collections.defaultdict(set)
        for i in range(n):
            setd[i].add(i)
        for a, b in Q: 
            if a in resd[b]:
                ans.append(False)
            else:
                ra, rb = find(a), find(b)
                if ra == rb:
                    ans.append(True)
                else:
                    valid = True
                    sb =setd[rb]
                    for cand in outer[rb]:
                        if cand in setd[ra]:
                            valid = False
                            ans.append(False)
                            break
                    if valid:
                        union(a, b)
                        ans.append(True)
        return ans