A Stroll Around the Matrix (Codeforces 1609G)
Tags: Greedy, data structures

  William has two arrays of numbers $$$a_1, a_2, \dots, a_n$$$ and $$$b_1, b_2, \dots, b_m$$$. The arrays satisfy the conditions of being convex. Formally an array $$$c$$$ of length $$$k$$$ is considered convex if $$$c_i - c_{i - 1} < c_{i + 1} - c_i$$$ for all $$$i$$$ from $$$2$$$ to $$$k - 1$$$ and $$$c_1 < c_2$$$.Throughout William's life he observed $$$q$$$ changes of two types happening to the arrays:   Add the arithmetic progression $$$d, d \cdot 2, d \cdot 3, \dots, d \cdot k$$$ to the suffix of the array $$$a$$$ of length $$$k$$$. The array after the change looks like this: $$$[a_1, a_2, \dots, a_{n - k}, a_{n - k + 1} + d, a_{n - k + 2} + d \cdot 2, \dots, a_n + d \cdot k]$$$.  The same operation, but for array $$$b$$$. After each change a matrix $$$d$$$ is created from arrays $$$a$$$ and $$$b$$$, of size $$$n \times m$$$, where $$$d_{i, j}=a_i + b_j$$$. William wants to get from cell ($$$1, 1$$$) to cell ($$$n, m$$$) of this matrix. From cell ($$$x, y$$$) he can only move to cells ($$$x + 1, y$$$) and ($$$x, y + 1$$$). The length of a path is calculated as the sum of numbers in cells visited by William, including the first and the last cells.After each change William wants you to help find out the minimal length of the path he could take.

Input: The first line contains three integers $$$n$$$, $$$m$$$ and $$$q$$$ ($$$2 \le n \le 100, 2 \le m \le 10^5$$$, $$$1 \le q \le 10^5$$$), the sizes of the arrays and the number of changes.The second line contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$1 \le a_i \le 10^{12}$$$), the contents of array $$$a$$$.The third line contains $$$m$$$ integers $$$b_1, b_2, \dots, b_m$$$ ($$$1 \le b_i \le 10^{12}$$$), the contents of array $$$b$$$.Each of the next $$$q$$$ lines contains three integers $$$type$$$, $$$k$$$ and $$$d$$$ ($$$1 \le type \le 2$$$, if $$$type = 1$$$, then $$$1 \le k \le n$$$ otherwise $$$1 \le k \le m$$$, $$$1 \le d \le 10^3$$$).

Output: After each change, output one integer, the minimum length of the path in the constructed matrix.


Sample Inputs:
5 3 4
1 2 4 7 11
5 7 10
1 3 2
2 2 5
1 5 4
2 1 7

5 6 7
4 9 22 118 226
7 94 238 395 565 738
2 1 95
1 4 54
1 2 5
1 2 87
2 6 62
2 1 143
1 1 77

Sample Outputs:
98
128
219
229

3639
5122
5162
5617
7663
7806
7960

Solution (Python):
import sys
raw_input = sys.stdin.readline

class BIT(object):

    def __init__(self, n):
        self.__bit = [0] * (n + 1)

    def add(self, i, val):
        while i < len(self.__bit):
            self.__bit[i] += val
            i += i & -i

    def query(self, i):
        ret = 0
        while i > 0:
            ret += self.__bit[i]
            i -= i & -i
        return ret

    def search(self, val):
        floor_log2_n = (len(self.__bit) - 1).bit_length() - 1
        pow_i = 2 ** floor_log2_n
        total = pos = 0
        for _ in reversed(range(floor_log2_n + 1)):
            if pos + pow_i < len(self.__bit) and total + self.__bit[pos + pow_i] < val:
                total += self.__bit[pos + pow_i]
                pos += pow_i
            pow_i >>= 1
        return pos

def solution():
    (n, m, q) = list(map(int, input().strip().split()))
    arr = list(map(int, input().strip().split()))
    brr = list(map(int, input().strip().split()))
    for i in reversed(range(1, n)):
        arr[i] -= arr[i - 1]
    for i in reversed(range(1, m)):
        brr[i] -= brr[i - 1]
    curr = (arr[0] + brr[0]) * (n + m - 1) + sum((brr[i] * (m - i) for i in range(1, m)))
    (bit1, bit2, bit3) = (BIT(m), BIT(m), BIT(m))
    for i in range(1, m):
        bit1.add(i, brr[i])
        bit1.add(i + 1, -brr[i])
        bit2.add(i, brr[i])
    bit1.add(m, float('inf'))
    result = []
    for _ in range(q):
        (a, b, c) = list(map(int, input().strip().split()))
        if a == 1:
            for i in range(b):
                arr[i + (n - b)] += c
            if b == n:
                curr += c * (n + m - 1)
        else:
            if b == m:
                curr += c * (n + m - 1)
                b -= 1
            curr += b * (b + 1) // 2 * c
            bit1.add(m - b, c)
            bit3.add(m - b, c)
            bit2.add(m - b, -c * (m - b - 1))
        ans = curr
        for i in range(1, n):
            idx = bit1.search(arr[i])
            ans += bit3.query(idx) * idx + bit2.query(idx)
            ans += arr[i] * (n + m - i - idx - 1)
        result.append(ans)
    return '\n'.join(map(str, result))
print('%s' % solution())

Solution (Python):
import sys
raw_input = sys.stdin.readline

class BIT(object):

    def __init__(self, n):
        self.__bit = [0] * (n + 1)

    def add(self, i, val):
        while i < len(self.__bit):
            self.__bit[i] += val
            i += i & -i

    def query(self, i):
        ret = 0
        while i > 0:
            ret += self.__bit[i]
            i -= i & -i
        return ret

    def search(self, val):
        floor_log2_n = (len(self.__bit) - 1).bit_length() - 1
        pow_i = 2 ** floor_log2_n
        total = pos = 0
        for _ in reversed(range(floor_log2_n + 1)):
            if pos + pow_i < len(self.__bit) and total + self.__bit[pos + pow_i] <= val:
                total += self.__bit[pos + pow_i]
                pos += pow_i
            pow_i >>= 1
        return pos

def solution():
    (n, m, q) = list(map(int, input().strip().split()))
    arr = list(map(int, input().strip().split()))
    brr = list(map(int, input().strip().split()))
    for i in reversed(range(1, n)):
        arr[i] -= arr[i - 1]
    for i in reversed(range(1, m)):
        brr[i] -= brr[i - 1]
    curr = (arr[0] + brr[0]) * (n + m - 1) + sum((brr[i] * (m - i) for i in range(1, m)))
    (bit1, bit2, bit3) = (BIT(m), BIT(m), BIT(m))
    for i in range(1, m):
        bit1.add(i, brr[i])
        bit1.add(i + 1, -brr[i])
        bit2.add(i, brr[i])
    bit1.add(m, float('inf'))
    result = []
    for _ in range(q):
        (a, b, c) = list(map(int, input().strip().split()))
        if a == 1:
            for i in range(b):
                arr[i + (n - b)] += c
            if b == n:
                curr += c * (n + m - 1)
        else:
            if b == m:
                curr += c * (n + m - 1)
                b -= 1
            curr += b * (b + 1) // 2 * c
            bit1.add(m - b, c)
            bit3.add(m - b, c)
            bit2.add(m - b, -c * (m - b - 1))
        ans = curr
        for i in range(1, n):
            idx = bit1.search(arr[i])
            ans += bit3.query(idx) * idx + bit2.query(idx)
            ans += arr[i] * (n + m - i - idx - 1)
        result.append(ans)
    return '\n'.join(map(str, result))
print('%s' % solution())

Solution (Python):
class BIT(object):

    def __init__(self, n):
        self.__bit = [0] * (n + 1)

    def add(self, i, val):
        while i < len(self.__bit):
            self.__bit[i] += val
            i += i & -i

    def query(self, i):
        ret = 0
        while i > 0:
            ret += self.__bit[i]
            i -= i & -i
        return ret

    def search(self, val):
        floor_log2_n = (len(self.__bit) - 1).bit_length() - 1
        pow_i = 2 ** floor_log2_n
        total = pos = 0
        for _ in reversed(range(floor_log2_n + 1)):
            if pos + pow_i < len(self.__bit) and total + self.__bit[pos + pow_i] < val:
                total += self.__bit[pos + pow_i]
                pos += pow_i
            pow_i >>= 1
        return pos

def solution():
    (n, m, q) = list(map(int, input().strip().split()))
    arr = list(map(int, input().strip().split()))
    brr = list(map(int, input().strip().split()))
    for i in reversed(range(1, n)):
        arr[i] -= arr[i - 1]
    for i in reversed(range(1, m)):
        brr[i] -= brr[i - 1]
    curr = (arr[0] + brr[0]) * (n + m - 1) + sum((brr[i] * (m - i) for i in range(1, m)))
    (bit1, bit2, bit3) = (BIT(m), BIT(m), BIT(m))
    for i in range(1, m):
        bit1.add(i, brr[i])
        bit1.add(i + 1, -brr[i])
        bit2.add(i, brr[i])
    bit1.add(m, float('inf'))
    result = []
    for _ in range(q):
        (a, b, c) = list(map(int, input().strip().split()))
        if a == 1:
            for i in range(b):
                arr[i + (n - b)] += c
            if b == n:
                curr += c * (n + m - 1)
        else:
            if b == m:
                curr += c * (n + m - 1)
                b -= 1
            curr += b * (b + 1) // 2 * c
            bit1.add(m - b, c)
            bit3.add(m - b, c)
            bit2.add(m - b, -c * (m - b - 1))
        ans = curr
        for i in range(1, n):
            idx = bit1.search(arr[i])
            ans += bit3.query(idx) * idx + bit2.query(idx)
            ans += arr[i] * (n + m - i - idx - 1)
        result.append(ans)
    return '\n'.join(map(str, result))
print('%s' % solution())