Last Man Standing (Codeforces 1879F)
Tags: Others, number theory

There are $$$n$$$ heroes in a videogame. Each hero has some health value $$$h$$$ and initial armor value $$$a$$$. Let the current value of armor be $$$a_{\mathit{cur}}$$$, initially equal to $$$a$$$.When $$$x$$$ points of damage are inflicted on a hero, the following happens: if $$$x < a_{\mathit{cur}}$$$, then $$$x$$$ gets subtracted from $$$a_{\mathit{cur}}$$$; otherwise, $$$1$$$ gets subtracted from $$$h$$$ and $$$a_{\mathit{cur}}$$$ gets assigned back to $$$a$$$.In the start of the game, you choose the value $$$x$$$ (an integer strictly greater than $$$0$$$, arbitrarily large). Then you keep attacking all heroes in rounds: in one round, you inflict $$$x$$$ points of damage to all alive heroes. A hero dies when his health becomes $$$0$$$. The game ends when all heroes are dead.The last hero to die earns the number of points, equal to the number of rounds he was the only hero alive. The other heroes get $$$0$$$ points. In particular, if the last round ends with multiple heroes dying, then every hero gets $$$0$$$ points.The game is played for every possible $$$x$$$ (from $$$1$$$ to infinity). The points are reset between the games. What's the maximum number of points each hero has had?

Input: The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10$$$) — the number of testcases.The first line of each testcase contains a single integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — the number of heroes.The second line contains $$$n$$$ integers $$$h_1, h_2, \dots, h_n$$$ ($$$1 \le h_i \le 2 \cdot 10^5$$$) — the health value of each hero.The third line contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$1 \le a_i \le 2 \cdot 10^5$$$) — the initial armor value of each hero.

Output: For each testcase, print $$$n$$$ integers — the maximum number of points each hero has had over the games played for every possible $$$x$$$.

Note: In the first testcase, the game for $$$x = 1$$$ is played as follows:   before all rounds: the heroes have $$$h = [3, 1, 2]$$$, $$$a_{\mathit{cur}} = [3, 11, 5]$$$;  round $$$1$$$: $$$1$$$ damage is inflicted on every hero: $$$h$$$ remains $$$[3, 1, 2]$$$, $$$a_{\mathit{cur}}$$$ becomes $$$[2, 10, 4]$$$;  round $$$2$$$: $$$h = [3, 1, 2]$$$, $$$a_{\mathit{cur}} = [1, 9, 3]$$$;  round $$$3$$$: the first hero runs out of armor, so he loses a health point: $$$h = [2, 1, 2]$$$, $$$a_{\mathit{cur}} = [3, 8, 2]$$$;  ...  round $$$9$$$: the first hero dies, since his health reaches $$$0$$$: $$$h = [0, 1, 1]$$$, $$$a_{\mathit{cur}} = [0, 2, 1]$$$;  round $$$10$$$: the third hero dies: $$$h = [0, 1, 0]$$$, $$$a_{\mathit{cur}} = [0, 1, 0]$$$;  round $$$11$$$: the second hero dies: $$$h = [0, 0, 0]$$$, $$$a_{\mathit{cur}} = [0, 0, 0]$$$. The second hero was the last hero to die, and he was the only hero alive during one round. Thus, he gets $$$1$$$ point for that game.The game for $$$x = 4$$$ is played as follows:   round $$$1$$$: $$$h = [2, 1, 2]$$$, $$$a_{\mathit{cur}} = [3, 7, 1]$$$;  round $$$2$$$: $$$h = [1, 1, 1]$$$, $$$a_{\mathit{cur}} = [3, 3, 5]$$$;  round $$$3$$$: $$$h = [0, 0, 1]$$$, $$$a_{\mathit{cur}} = [0, 0, 1]$$$;  round $$$4$$$: $$$h = [0, 0, 0]$$$, $$$a_{\mathit{cur}} = [0, 0, 0]$$$; The third hero was the last hero to die, and he was the only hero alive during one round.

Sample Inputs:
3
3
3 1 2
3 11 5
1
100
200
4
5 9 5 1
9 2 9 10

Sample Outputs:
1 1 1 
20000 
0 4 0 0

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

def f(u, v):
    return u << 20 ^ v
t = int(input())
ans = []
for _ in range(t):
    n = int(input())
    h = list(map(int, input().split())) + [-1]
    a = list(map(int, input().split()))
    z = [f(a[i], i) for i in range(n)]
    z = [i & 1048575 for i in sorted(z)] + [n]
    (ma1, ma2) = ([-1] * n, [-1] * n)
    (m1, m2) = (n, n)
    p = [n] * (n + 1)
    for i in range(n - 1, -1, -1):
        j = z[i]
        p[j] = i
        if h[m1] < h[j]:
            (m1, m2) = (j, m1)
        elif h[m2] < h[j]:
            m2 = j
        (ma1[i], ma2[i]) = (m1, m2)
    m = max(a) + 1
    s0 = [0] * (m + 1)
    for i in a:
        s0[i + 1] += 1
    for i in range(1, m + 1):
        s0[i] += s0[i - 1]
    ans0 = [0] * n
    for x in range(1, m + 1):
        (u, v, j) = (0, 0, -1)
        y = 1
        for l in range(1, m + 1, x):
            r = min(l + x, m)
            if s0[l] == s0[r]:
                y += 1
                continue
            (ll, rr) = (s0[l], s0[r] - 1)
            i = ma1[ll]
            if ll <= p[i] <= rr:
                s = y * h[i]
                if u < s:
                    (u, v, j) = (s, u, i)
                elif v < s:
                    v = s
            i = ma2[ll]
            if ll <= p[i] <= rr:
                s = y * h[i]
                if u < s:
                    (u, v, j) = (s, u, i)
                elif v < s:
                    v = s
            y += 1
        ans0[j] = max(ans0[j], u - v)
    ans.append(' '.join(map(str, ans0)))
sys.stdout.write('\n'.join(map(str, ans)))

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

def f(u, v):
    return u << 20 ^ v
t = int(input())
for _ in range(t):
    n = int(input())
    h = list(map(int, input().split())) + [-1]
    a = list(map(int, input().split()))
    z = [f(a[i], i) for i in range(n)]
    z = [i & 1048575 for i in sorted(z)] + [n]
    (ma1, ma2) = ([-1] * n, [-1] * n)
    (m1, m2) = (n, n)
    p = [n] * (n + 1)
    for i in range(n - 1, -1, -1):
        j = z[i]
        p[j] = i
        if h[m1] < h[j]:
            (m1, m2) = (j, m1)
        elif h[m2] < h[j]:
            m2 = j
        (ma1[i], ma2[i]) = (m1, m2)
    m = max(a) + 1
    s0 = [0] * (m + 1)
    for i in a:
        s0[i + 1] += 1
    for i in range(1, m + 1):
        s0[i] += s0[i - 1]
    ans = [0] * n
    for x in range(1, m + 1):
        (u, v, j) = (0, 0, -1)
        y = 1
        for l in range(1, m + 1, x):
            r = min(l + x, m)
            if s0[l] == s0[r]:
                y += 1
                continue
            (ll, rr) = (s0[l], s0[r] - 1)
            i = ma1[ll]
            if ll <= p[i] <= rr:
                s = y * h[i]
                if u < s:
                    (u, v, j) = (s, u, i)
                elif v < s:
                    v = s
            i = ma2[ll]
            if ll <= p[i] <= rr:
                s = y * h[i]
                if u < s:
                    (u, v, j) = (s, u, i)
                elif v < s:
                    v = s
            y += 1
        ans[j] = max(ans[j], u - v)
    sys.stdout.write(' '.join(map(str, ans)) + '\n')

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

def f(u, v):
    return u << 20 ^ v
t = int(input())
ans = []
for _ in range(t):
    n = int(input())
    h = list(map(int, input().split())) + [-1]
    a = list(map(int, input().split()))
    z = [f(a[i], i) for i in range(n)]
    z = [i & 1048575 for i in sorted(z)]
    (ma1, ma2) = ([-1] * n, [-1] * n)
    (m1, m2) = (n, n)
    for i in range(n - 1, -1, -1):
        j = z[i]
        if h[m1] < h[j]:
            (m1, m2) = (j, m1)
        elif h[m2] < h[j]:
            m2 = j
        (ma1[i], ma2[i]) = (m1, m2)
    m = max(a) + 1
    s0 = [0] * (m + 1)
    for i in a:
        s0[i + 1] += 1
    for i in range(1, m + 1):
        s0[i] += s0[i - 1]
    ans0 = [0] * n
    for x in range(1, m + 1):
        (u, v, j) = (0, 0, -1)
        for l in range(1, m + 1, x):
            r = min(l + x, m)
            if s0[l] == s0[r]:
                continue
            for i in [ma1[s0[l]], ma2[s0[l]]]:
                if i == n or i == j:
                    continue
                s = ((a[i] - 1) // x + 1) * h[i]
                if u < s:
                    (u, v, j) = (s, u, i)
                elif v < s:
                    v = s
        ans0[j] = max(ans0[j], u - v)
    ans.append(' '.join(map(str, ans0)))
sys.stdout.write('\n'.join(map(str, ans)))