New Year Concert (Codeforces 1632D)
Tags: Greedy, number theory

New Year is just around the corner, which means that in School 179, preparations for the concert are in full swing.There are $$$n$$$ classes in the school, numbered from $$$1$$$ to $$$n$$$, the $$$i$$$-th class has prepared a scene of length $$$a_i$$$ minutes.As the main one responsible for holding the concert, Idnar knows that if a concert has $$$k$$$ scenes of lengths $$$b_1$$$, $$$b_2$$$, $$$\ldots$$$, $$$b_k$$$ minutes, then the audience will get bored if there exist two integers $$$l$$$ and $$$r$$$ such that $$$1 \le l \le r \le k$$$ and $$$\gcd(b_l, b_{l + 1}, \ldots, b_{r - 1}, b_r) = r - l + 1$$$, where $$$\gcd(b_l, b_{l + 1}, \ldots, b_{r - 1}, b_r)$$$ is equal to the greatest common divisor (GCD) of the numbers $$$b_l$$$, $$$b_{l + 1}$$$, $$$\ldots$$$, $$$b_{r - 1}$$$, $$$b_r$$$.To avoid boring the audience, Idnar can ask any number of times (possibly zero) for the $$$t$$$-th class ($$$1 \le t \le k$$$) to make a new scene $$$d$$$ minutes in length, where $$$d$$$ can be any positive integer. Thus, after this operation, $$$b_t$$$ is equal to $$$d$$$. Note that $$$t$$$ and $$$d$$$ can be different for each operation.For a sequence of scene lengths $$$b_1$$$, $$$b_2$$$, $$$\ldots$$$, $$$b_{k}$$$, let $$$f(b)$$$ be the minimum number of classes Idnar has to ask to change their scene if he wants to avoid boring the audience.Idnar hasn't decided which scenes will be allowed for the concert, so he wants to know the value of $$$f$$$ for each non-empty prefix of $$$a$$$. In other words, Idnar wants to know the values of $$$f(a_1)$$$, $$$f(a_1$$$,$$$a_2)$$$, $$$\ldots$$$, $$$f(a_1$$$,$$$a_2$$$,$$$\ldots$$$,$$$a_n)$$$.

Input: The first line contains a single integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — the number of classes in the school.The second line contains $$$n$$$ positive integers $$$a_1$$$, $$$a_2$$$, $$$\ldots$$$, $$$a_n$$$ ($$$1 \le a_i \le 10^9$$$) — the lengths of the class scenes.

Output: Print a sequence of $$$n$$$ integers in a single line — $$$f(a_1)$$$, $$$f(a_1$$$,$$$a_2)$$$, $$$\ldots$$$, $$$f(a_1$$$,$$$a_2$$$,$$$\ldots$$$,$$$a_n)$$$.

Note: In the first test we can change $$$1$$$ to $$$2$$$, so the answer is $$$1$$$.In the second test:   $$$[1]$$$ can be changed into $$$[2]$$$,  $$$[1, 4]$$$ can be changed into $$$[3, 4]$$$,  $$$[1, 4, 2]$$$ can be changed into $$$[2, 3, 2]$$$. 

Sample Inputs:
1
1

3
1 4 2

7
2 12 4 8 18 3 6

Sample Outputs:
1

1 1 2

0 1 1 1 2 2 2

Solution (Python):
import sys
import math

def solve():
    inp = sys.stdin.readline
    gcd = math.gcd
    n = int(inp())
    cnt = 0
    ans = [0] * n
    s = []
    i = 0
    for x in map(int, inp().split()):
        s.append([x, i])
        for j in range(len(s) - 1, -1, -1):
            x = gcd(s[j][0], x)
            s[j][0] = x
            if j + 1 < len(s) and s[j][0] == s[j + 1][0]:
                s.pop(j + 1)
        for j in range(len(s) - 1, -1, -1):
            if i - s[j][1] + 1 >= s[j][0] and (j + 1 >= len(s) or s[j + 1][1] > i - s[j][0] + 1):
                s = []
                cnt += 1
                break
        ans[i] = cnt
        i += 1
    print(' '.join(map(str, ans)))

def main():
    solve()
if __name__ == '__main__':
    main()

Solution (Python):
def sum(a, b):
    return a + b
import math
a = input()
nums = [int(x) for x in input().split(' ')]
f_vals = []
last_f = 0
current_to_gcd = []
cur_index = 0
for x in nums:
    if x == 1:
        last_f += 1
        f_vals.append(last_f)
        current_to_gcd = []
    else:
        prev_pos = cur_index
        new_cgid = []
        mod = 0
        new_cgid.append([x, cur_index])
        for (val, pos) in current_to_gcd:
            g = math.gcd(x, val)
            if cur_index - prev_pos + 1 < g and cur_index - pos + 1 >= g:
                current_to_gcd = []
                last_f += 1
                mod = 1
                f_vals.append(last_f)
                break
            else:
                new_cgid.append([g, pos])
                prev_pos = pos
        if mod == 0:
            modified_new = []
            i = 1
            modified_new.append(new_cgid[0])
            cur = new_cgid[0][0]
            while i < len(new_cgid):
                if new_cgid[i][0] != cur:
                    cur = new_cgid[i][0]
                    modified_new.append(new_cgid[i])
                else:
                    modified_new[len(modified_new) - 1][1] = new_cgid[i][1]
                i += 1
            current_to_gcd = modified_new
            f_vals.append(last_f)
    cur_index += 1
print(*f_vals)

Solution (Python):
""""""
''
''
from math import gcd as g
from functools import cmp_to_key as ck

def cp(a, b):
    if a[1] < b[1]:
        return -1
    if a[1] > b[1]:
        return 1
    return 0
n = int(input())
ar = [int(i) for i in input().split()]
s = [{}]
ind = 0
for i in ar:
    prev = s[-1]
    chd = {i: (ind, ind)}
    for gcd in prev:
        (st, ed) = prev[gcd]
        gcd = g(gcd, i)
        try:
            (a, d) = chd[gcd]
            a = min(a, st)
            d = max(d, ed)
            chd[gcd] = (a, d)
        except:
            chd[gcd] = (st, ed)
    s.append(chd)
    ind += 1
sgs = []
ind = -1
for i in s:
    for gcd in i:
        (st, ed) = i[gcd]
        if st <= ind - gcd + 1 <= ed:
            sgs.append((ind - gcd + 1, ind))
    ind += 1
sgs = sorted(sgs, key=ck(cp))
rt = -1
res = [0 for i in range(n)]
for (st, ed) in sgs:
    if rt < st:
        rt = ed
        res[rt] = 1
x = 0
for i in range(n):
    res[i] += x
    x = res[i]
print(' '.join(map(str, res)))