Music Festival (Codeforces 1802E)
Tags: DP, binary search

 The boy Vitya loves to listen to music very much. He knows that $$$n$$$ albums are due to be released this Friday, $$$i$$$-th of which contains $$$k_i$$$ tracks. Of course, Vitya has already listened to all the tracks, and knows that in the $$$i$$$-th album, the coolness of the $$$j$$$-th track is equal to $$$a_{i,j}$$$.Vitya has a friend Masha, whom he really wants to invite to the festival, where his favorite bands perform. However, in order for a friend to agree, she must first evaluate the released novelties. Vitya knows that if Masha listens to a track that was cooler than all the previous ones, she will get 1 unit of impression. Unfortunately, albums can only be listened to in their entirety, without changing the songs in them in places.Help Vitya find such an order of albums so that Masha's impression turns out to be as much as possible, and she definitely went to the festival with him. 

Input: Each test consists of multiple test cases. The first line contains a single integer t ($$$1 \le t \le 200\,000$$$) — the number of test cases. The description of test cases follows.The first line of each test case contains a single integer $$$n$$$ ($$$1 \le n \le 200\,000$$$) — number of albums.The album descriptions follow. Each album description consists of two lines:The first line contains a single integer $$$k_i$$$ ($$$1 \le k_i \le 200\,000$$$) — the number of tracks in the $$$i$$$th album.The following line contains $$$k_i$$$ integers $$$a_{i, 1},\ a_{i, 2},\ a_{i, 3},\ \ldots,\ a_{i, k_i}$$$ ($$$1 \le a_{i,j} \le 200\,000$$$) — the coolness of the tracks in the $$$i$$$ album. Denote for $$$\sum k_i$$$ the sum of all $$$k_i$$$. It is guaranteed that $$$\sum k_i \le 200\,000$$$. 

Output: For each test case print the singular number  — the maximum impression that Masha can get. 

Note: In the first test example, the optimal order is listening to the 4th, 2nd, 3rd and 1st albums. In this case, Masha will listen to the tracks in the following order: 1; 7; 8, 6; 4, 9, 4, 6, 8 and will receive 4 units of impression.In the second test example, you must first listen to the 1st, then the 4th, and in any order the 2nd and 3rd.   In this case, Masha will get the maximum impression, and for every song in the 1st and 4th albums and nothing for the 2nd and 3rd. 

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

Sample Outputs:
4
4

Solution (Python):
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = 'x' in file.mode or 'r' not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b'\n') + (not b)
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            (self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode('ascii'))
        self.read = lambda : self.buffer.read().decode('ascii')
        self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from collections import defaultdict as dd
from collections import deque
import bisect
import heapq

def ri():
    return int(input())

def rl():
    return list(map(int, input().split()))

def normalize(A):
    if not A:
        return []
    top = A[0]
    out = A[:1]
    for a in A:
        if a > top:
            out.append(a)
            top = a
    return out

def solve():
    n = ri()
    disks = []
    for i in range(n):
        k = ri()
        disks.append(normalize(rl()))
    disks.sort(key=lambda x: x[-1])
    dp = [[0, 0]]
    for disk in disks:
        top = disk[-1]
        if top > dp[-1][0]:
            curr_best = max(len(disk), dp[-1][1])
            dp.append([top, curr_best])
        partial_score = 0
        for value in disk[::-1]:
            partial_score += 1
            lo = 0
            hi = len(dp) - 1
            while lo < hi - 1:
                mid = (lo + hi) // 2
                if dp[mid][0] < value:
                    lo = mid
                else:
                    hi = mid
            check = partial_score + dp[lo][1]
            dp[-1][1] = max(dp[-1][1], check)
    print(max((x[1] for x in dp)))
mode = 'T'
if mode == 'T':
    t = ri()
    for i in range(t):
        solve()
else:
    solve()

Solution (Python):
def solve(albums):
    m = len(albums)
    albums2 = []
    for album in albums:
        max_coolness = 0
        arr = []
        for coolness in album:
            if coolness > max_coolness:
                arr.append(coolness)
                max_coolness = coolness
        albums2.append(arr)
    albums2.sort(key=lambda arr: arr[-1])
    max_coolness_for_album = [0] * m
    for i in range(m):
        n = len(albums2[i])
        for j in range(n):
            (lo, hi) = (-1, i)
            while lo < hi:
                mid = (lo + hi + 1) // 2
                if albums2[mid][-1] < albums2[i][j]:
                    lo = mid
                else:
                    hi = mid - 1
            if lo == -1:
                left_coolness = 0
            else:
                left_coolness = max_coolness_for_album[lo]
            right_coolness = n - j
            max_coolness_for_album[i] = max(max_coolness_for_album[i], left_coolness + right_coolness)
        if i > 0:
            max_coolness_for_album[i] = max(max_coolness_for_album[i], max_coolness_for_album[i - 1])
    ans = max(max_coolness_for_album)
    return ans

def main():
    t = int(input())
    allans = []
    for _ in range(t):
        n = int(input())
        albums = []
        for __ in range(n):
            input()
            arr = readIntArr()
            albums.append(arr)
        ans = solve(albums)
        allans.append(ans)
    multiLineArrayPrint(allans)
    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(a, b):
    print('? {} {}'.format(a, b))
    sys.stdout.flush()
    return int(input())

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

Solution (Python):
import os, sys, threading
from random import randint, shuffle
from io import BytesIO, IOBase
from collections import defaultdict, deque, Counter
from bisect import bisect_left, bisect_right
from heapq import heappush, heappop, heapify
from functools import lru_cache, reduce
from itertools import accumulate, permutations
import math, copy
BUFSIZE = 8192

class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = 'x' in file.mode or 'r' not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b'\n') + (not b)
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            (self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode('ascii'))
        self.read = lambda : self.buffer.read().decode('ascii')
        self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
MOD = 998244353
from math import *

def main():
    from string import ascii_uppercase, ascii_lowercase

    def solve():
        n = int(input())
        arr = []
        for _ in range(n):
            _ = int(input())
            tmp = list(map(int, input().split()))
            st = []
            for a in tmp:
                if not st or st[-1] < a:
                    st.append(a)
            arr.append([x for x in st])
        dp = [0] * n
        idx = sorted(range(n), key=lambda x: arr[x][-1])
        reach = [arr[idx[0]][-1]]
        mx = len(arr[idx[0]])
        dp[0] = mx
        for i in range(1, n):
            j = idx[i]
            m = len(arr[j])
            for k in range(m)[::-1]:
                a = arr[j][k]
                pj = bisect_left(reach, a) - 1
                mx = max(mx, (dp[pj] if pj >= 0 else 0) + m - k)
            dp[i] = mx
            reach.append(arr[j][-1])
        print(mx)
        return
    t = int(input())
    for i in range(t):
        solve()
if __name__ == '__main__':
    threading.Thread(target=main).start()