Подкрутка II (Codeforces 1769C2)
Tags: DP, *special

В этой версии задачи $$$n \le 2 \cdot 10^5$$$ и $$$a_i \le 10^6$$$ (а также есть ограничение на сумму $$$n$$$ по наборам входных данных внутри одного теста).Вика за время работы в компании VK уже сделала $$$n$$$ коммитов в системе контроля версий. $$$i$$$-й коммит был сделан в $$$a_i$$$-й день работы Вики в компании. В некоторые дни Вика могла сделать несколько коммитов, а в другие — не сделать ни одного.Вику интересуют такие отрезки подряд идущих дней, что в каждый из этих дней у неё есть хотя бы один коммит. Чем длиннее будет самый длинный такой отрезок, тем более продуктивным сотрудником она будет себя ощущать.Недавно Вика нашла способ подкрутить время любого коммита вперёд, но не более чем на сутки. Таким образом, $$$i$$$-й коммит теперь может быть «сделан» либо в $$$a_i$$$-й, либо в $$$(a_i + 1)$$$-й день. Время каждого коммита можно подкрутить независимо от других — в частности, можно как оставить всем коммитам исходное время, так и перенести все коммиты ровно на день вперёд.Найдите длину самого длинного возможного отрезка подряд идущих дней, в каждый из которых у Вики в профиле будет отображаться хотя бы один коммит, после возможной подкрутки времени некоторых коммитов.

Input: Каждый тест состоит из нескольких наборов входных данных. В первой строке находится одно целое число $$$t$$$ ($$$1 \le t \le 100$$$) — количество наборов входных данных. Далее следует описание наборов входных данных.Первая строка каждого набора входных данных содержит одно целое число $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — число коммитов.Вторая строка содержит $$$n$$$ целых чисел $$$a_1, a_2, \ldots, a_n$$$ в неубывающем порядке ($$$1 \le a_1 \le a_2 \le \ldots \le a_n \le 10^6$$$) — номера дней, в которые были сделаны коммиты.Гарантируется, что сумма $$$n$$$ по всем наборам входных данных не превосходит $$$2 \cdot 10^5$$$.

Output: Для каждого набора входных данных выведите одно целое число — максимальную возможную длину отрезка дней, в каждый из которых у Вики в профиле будет отображаться хотя бы один коммит, после возможной подкрутки времени некоторых коммитов вперёд не более чем на сутки.

Note: В первом наборе входных данных можно поменять дату коммита в день $$$3$$$ на день $$$4$$$, дату коммита в день $$$4$$$ — на день $$$5$$$, а дату любого из коммитов в день $$$6$$$ — на день $$$7$$$. Тогда в каждый из дней $$$4$$$, $$$5$$$, $$$6$$$, $$$7$$$ и $$$8$$$ в профиле Вики будет отображаться хотя бы один коммит, и наибольший отрезок из подряд идущих дней с коммитами — $$$[4; 8]$$$ — будет иметь длину $$$5$$$.Во втором наборе входных данных можно либо оставить все коммиты как есть, либо перенести каждый коммит на день вперёд. В любом случае длина отрезка дней составит $$$6$$$.В третьем наборе входных данных Вика сделала много коммитов, но все в один и тот же день с номером $$$10$$$. В лучшем случае отрезок дней достигнет длины $$$2$$$ — если какие-то коммиты оставить на день $$$10$$$, а другие перенести на день $$$11$$$.

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

Sample Outputs:
5
6
2

Solution (Python):
for _ in range(int(input())):
    n = int(input())
    a = list(map(int, input().split()))
    d = -2
    count = 0
    bf = 0
    sUm = 0
    maxx = 0
    buf = 0
    for i in range(n):
        if a[i] - d == 1:
            count += 1
            sUm += 1
        elif a[i] - d == 0:
            bf = 1
        elif a[i] - d == 2:
            if bf == 1:
                sUm += 2
                bf = 0
                count = 1
            else:
                if sUm > maxx:
                    maxx = sUm
                sUm = count + 1
                count = 1
        else:
            count = 1
            sUm += bf
            if sUm > maxx:
                maxx = sUm
            bf = 0
            sUm = 1
        d = a[i]
    sUm += bf
    if sUm > maxx:
        maxx = sUm
    print(maxx)

Solution (Python):
otv = []
for _ in range(int(input())):
    n = int(input())
    a = list(map(int, input().split()))
    c = 1
    m = -1
    lend = 1
    lendh_buf = 0
    for i in range(1, len(a)):
        if a[i - 1] == a[i]:
            c += 1
        elif a[i] - a[i - 1] == 1:
            if c > 1:
                c = 2
            else:
                c = 1
            lend += 1
        elif a[i] - a[i - 1] == 2:
            if c > 1:
                lendh_buf = lend + 1
                lend += 2
                c = 1
            elif lendh_buf != 0:
                m = max(m, lend)
                lend = lend - lendh_buf + 1
                lendh_buf = lend - 1
                c = 1
            else:
                lendh_buf = lend
                lend += 1
                c = 1
        elif a[i] - a[i - 1] > 2:
            if c > 1:
                m = max(lend + 1, m)
                lend = 1
                lendh_buf = 0
                c = 1
            else:
                m = max(lend, m)
                lend = 1
                lendh_buf = 0
                c = 1
    if lend != 0:
        if c > 1:
            m = max(m, lend + 1)
        else:
            m = max(m, lend)
    otv += [str(m)]
print('\n'.join(otv))

Solution (Python):
def solution(n, commits):
    max_len = 1
    if n == 1:
        return 1
    index = 0
    while index < n:
        start = commits[index]
        finish = start
        cnt_zeros = 1
        i = index
        while i < n:
            i += 1
            if i == n:
                break
            if commits[i] < finish:
                cnt_zeros = 0
                continue
            if commits[i] == finish:
                finish += 1
                cnt_zeros = 0
                continue
            if commits[i] == finish + 1:
                finish += 1
                cnt_zeros += 1
                continue
            break
        max_len = max(max_len, finish - start + 1)
        tmp_index = i
        while cnt_zeros > 0:
            i = tmp_index - cnt_zeros
            start = commits[i] + 1
            finish = start
            cnt_zeros = 0
            while i < n:
                i += 1
                if i == n:
                    break
                if commits[i] < finish:
                    cnt_zeros = 0
                    continue
                if commits[i] == finish:
                    finish += 1
                    cnt_zeros = 0
                    continue
                if commits[i] == finish + 1:
                    finish += 1
                    cnt_zeros += 1
                    continue
                break
            max_len = max(max_len, finish - start + 1)
            tmp_index = i
        index = tmp_index
    return max_len
if __name__ == '__main__':
    t = int(input())
    for _ in range(t):
        n = int(input())
        commits = list(map(int, input().split()))
        print(solution(n, commits))