Mateusz and Escape Room (Codeforces 1229F)
Tags: DP, dp

Mateusz likes to travel! However, on his $$$42$$$nd visit to Saint Computersburg there is not much left to sightsee. That's why he decided to go to an escape room with his friends!The team has solved all riddles flawlessly. There is only one riddle remaining — a huge circular table! There are $$$n$$$ weighing scales lying on top of the table, distributed along the circle. Each scale is adjacent to exactly two other scales: for each $$$i \in \{1, 2, \dots, n-1\}$$$, the $$$i$$$-th and the $$$(i+1)$$$-th scales are adjacent to each other, as well as the first and the $$$n$$$-th scale.The $$$i$$$-th scale initially contains $$$a_i$$$ heavy coins. Mateusz can perform moves — each move consists of fetching a single coin from one scale and putting it on any adjacent scale.It turns out that the riddle will be solved when there is a specific amount of coins on each of the scales. Specifically, each scale has parameters $$$l_i$$$ and $$$r_i$$$. If each coin lies on a single scale and for each $$$i$$$, the $$$i$$$-th scale contains at least $$$l_i$$$ and at most $$$r_i$$$ coins, the riddle will be solved and Mateusz's team will win!Mateusz is aiming for the best possible time. Therefore, he wants to solved the riddle as quickly as possible. What is the minimum possible number of moves required to fulfill all the conditions?

Input: The first line contains an integer $$$n$$$ ($$$3 \le n \le 35\,000$$$) — the number of weighing scales in the circle.The following $$$n$$$ lines describe the scales. The $$$i$$$-th of these lines describes the $$$i$$$-th scale and consists of three integers $$$a_i, l_i, r_i$$$ ($$$0 \le a_i \le 35\,000$$$, $$$0 \le l_i \le r_i \le 35\,000$$$).It's guaranteed that the riddle is solvable, that is, $$$\sum_{i=1}^n l_i \le \sum_{i=1}^n a_i \le \sum_{i=1}^n r_i$$$.

Output: Output one integer — the minimum number of operations required to solve the riddle.


Sample Inputs:
5
0 2 3
1 2 3
4 3 3
4 3 3
4 3 3

3
0 1 2
3 0 3
1 0 0

4
1 0 2
3 3 3
4 0 4
5 3 5

Sample Outputs:
4

1

0

Solution (Python):
import sys
import io
import os
BUFSIZE = 8192

class FastIO(io.IOBase):
    newlines = 0

    def __init__(self, file):
        self._file = file
        self._fd = file.fileno()
        self.buffer = io.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(io.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')

def print(*args, **kwargs):
    """"""
    (sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
    at_start = True
    for x in args:
        if not at_start:
            file.write(sep)
        file.write(str(x))
        at_start = False
    file.write(kwargs.pop('end', '\n'))
    if kwargs.pop('flush', False):
        file.flush()
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

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

def read_int_tuple():
    return map(int, input().split())

def read_int():
    return int(input())
read_str = input
INF = 1 << 60
from heapq import *

class SlopeTrick:

    def __init__(self):
        self.L = []
        self.R = []
        self.mi = 0
        self.la = 0
        self.ra = 0

    def add_const(self, a):
        self.mi += a

    def add_l(self, a):
        if self.R:
            r0 = self.R[0] + self.ra
            if a > r0:
                self.mi += a - r0
        heappush(self.L, -(heappushpop(self.R, a - self.ra) + self.ra - self.la))

    def add_r(self, a):
        if self.L:
            l0 = -self.L[0] + self.la
            if l0 > a:
                self.mi += l0 - a
        heappush(self.R, -heappushpop(self.L, -(a - self.la)) + self.la - self.ra)

    def add_abs(self, a):
        self.add_l(a)
        self.add_r(a)

    def slide(self, a, b=None):
        if b is None:
            b = a
        assert a <= b
        self.la += a
        self.ra += b

    @property
    def min(self):
        return self.mi

    def f(self, x):
        s = self.mi
        for r in self.R:
            tmp = x - (r + self.ra)
            if tmp > 0:
                s += tmp
        for l in self.L:
            tmp = -l + self.la - x
            if tmp > 0:
                s += tmp
        return s

    def debug(self):
        print('mi, L, R =', self.mi, self.L, self.la, self.R, self.ra)
        print([(x, self.f(x)) for x in range(-10, 11)])
MOD = 998244353

def solve():
    n = read_int()
    tot = 0
    (L, R) = ([0] * n, [0] * n)
    for i in range(n):
        (a, l, r) = read_int_tuple()
        (L[i], R[i]) = (a - l, a - r)
        tot += a

    def calc(x0: int) -> int:
        st = SlopeTrick()
        (st.L, st.R) = ([0] * n, [0] * n)
        st.slide(x0, x0)
        for i in range(1, n):
            st.slide(R[i], L[i])
            st.add_abs(0)
        st.slide(R[0], L[0])
        st.add_abs(0)
        return st.f(x0)

    def tersect(left, right, func):
        while left <= right:
            lmid = left + (right - left) // 3
            rmid = right - (right - left) // 3
            (fl, fr) = (func(lmid), func(rmid))
            if fl < fr:
                (res, right) = (fl, rmid - 1)
            else:
                (res, left) = (fr, lmid + 1)
        return res
    print(tersect(-tot, tot, calc))
T = 1
for t in range(T):
    solve()

Solution (Python):
import sys
import io
import os
BUFSIZE = 8192

class FastIO(io.IOBase):
    newlines = 0

    def __init__(self, file):
        self._file = file
        self._fd = file.fileno()
        self.buffer = io.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(io.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')

def print(*args, **kwargs):
    """"""
    (sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
    at_start = True
    for x in args:
        if not at_start:
            file.write(sep)
        file.write(str(x))
        at_start = False
    file.write(kwargs.pop('end', '\n'))
    if kwargs.pop('flush', False):
        file.flush()
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

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

def read_int_tuple():
    return map(int, input().split())

def read_int():
    return int(input())
read_str = input
INF = 1 << 60
from heapq import *

class SlopeTrick:

    def __init__(self):
        self.L = []
        self.R = []
        self.mi = 0
        self.la = 0
        self.ra = 0

    def add_const(self, a):
        self.mi += a

    def add_l(self, a):
        if self.R:
            r0 = self.R[0] + self.ra
            self.mi += max(a - r0, 0)
        heappush(self.L, -(heappushpop(self.R, a - self.ra) + self.ra - self.la))

    def add_r(self, a):
        if self.L:
            l0 = -self.L[0] + self.la
            self.mi += max(l0 - a, 0)
        heappush(self.R, -heappushpop(self.L, -(a - self.la)) + self.la - self.ra)

    def add_abs(self, a):
        self.add_l(a)
        self.add_r(a)

    def slide(self, a, b=None):
        if b is None:
            b = a
        assert a <= b
        self.la += a
        self.ra += b

    @property
    def min(self):
        return self.mi

    def f(self, x):
        s = self.mi
        for r in self.R:
            tmp = x - (r + self.ra)
            if tmp > 0:
                s += tmp
        for l in self.L:
            tmp = -l + self.la - x
            if tmp > 0:
                s += tmp
        return s

    def debug(self):
        print('mi, L, R =', self.mi, self.L, self.la, self.R, self.ra)
        print([(x, self.f(x)) for x in range(-10, 11)])
MOD = 998244353

def solve():
    n = read_int()
    tot = 0
    (L, R) = ([0] * n, [0] * n)
    for i in range(n):
        (a, l, r) = read_int_tuple()
        (L[i], R[i]) = (a - l, a - r)
        tot += a

    def calc(x0: int) -> int:
        st = SlopeTrick()
        (st.L, st.R) = ([0] * n, [0] * n)
        st.slide(x0, x0)
        for i in range(1, n):
            st.slide(R[i], L[i])
            st.add_abs(0)
        st.slide(R[0], L[0])
        st.add_abs(0)
        return st.f(x0)

    def tersect(left, right, func):
        while left <= right:
            lmid = left + (right - left) // 3
            rmid = right - (right - left) // 3
            (fl, fr) = (func(lmid), func(rmid))
            if fl < fr:
                (res, right) = (fl, rmid - 1)
            else:
                (res, left) = (fr, lmid + 1)
        return res
    print(tersect(-tot, tot, calc))
T = 1
for t in range(T):
    solve()

Solution (Python):
import sys
import io
import os
BUFSIZE = 8192

class FastIO(io.IOBase):
    newlines = 0

    def __init__(self, file):
        self._file = file
        self._fd = file.fileno()
        self.buffer = io.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(io.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')

def print(*args, **kwargs):
    """"""
    (sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
    at_start = True
    for x in args:
        if not at_start:
            file.write(sep)
        file.write(str(x))
        at_start = False
    file.write(kwargs.pop('end', '\n'))
    if kwargs.pop('flush', False):
        file.flush()
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

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

def read_int_tuple():
    return map(int, input().split())

def read_int():
    return int(input())
read_str = input
INF = 1 << 60
from heapq import *

class SlopeTrick:

    def __init__(self):
        self.L = []
        self.R = []
        self.mi = 0
        self.la = 0
        self.ra = 0

    def add_const(self, a):
        self.mi += a

    def add_l(self, a):
        if self.R:
            r0 = self.R[0] + self.ra
            self.mi += a - r0 if a > r0 else 0
        heappush(self.L, -(heappushpop(self.R, a - self.ra) + self.ra - self.la))

    def add_r(self, a):
        if self.L:
            l0 = -self.L[0] + self.la
            self.mi += l0 - a if l0 > a else 0
        heappush(self.R, -heappushpop(self.L, -(a - self.la)) + self.la - self.ra)

    def add_abs(self, a):
        self.add_l(a)
        self.add_r(a)

    def slide(self, a, b=None):
        if b is None:
            b = a
        assert a <= b
        self.la += a
        self.ra += b

    @property
    def min(self):
        return self.mi

    def f(self, x):
        s = self.mi
        for r in self.R:
            s += x - (r + self.ra) if x > r + self.ra else 0
        for l in self.L:
            s += -l + self.la - x if -l + self.la > x else 0
        return s

    def debug(self):
        print('mi, L, R =', self.mi, self.L, self.la, self.R, self.ra)
        print([(x, self.f(x)) for x in range(-10, 11)])

    def get_destr(self, x: int) -> int:
        res = self.mi
        while self.L:
            tmp = heappop(self.L) - x
            if tmp > 0:
                res += tmp
        while self.R:
            tmp = x - heappop(self.R)
            if tmp > 0:
                res += tmp
        return res
from heapq import heappop, heappush
from typing import Tuple
INF = int(1e+18)
MOD = 998244353

def solve():
    n = read_int()
    tot = 0
    (L, R) = ([0] * n, [0] * n)
    for i in range(n):
        (a, l, r) = read_int_tuple()
        (L[i], R[i]) = (a - l, a - r)
        tot += a
    st = SlopeTrick()
    (st.L, st.R) = ([0] * n, [0] * n)

    def calc(x0: int) -> int:
        (st.L, st.R) = ([0] * n, [0] * n)
        st.la = st.ra = st.mi = 0
        st.slide(x0, x0)
        for i in range(1, n):
            st.slide(R[i], L[i])
            st.add_abs(0)
        st.slide(R[0], L[0])
        st.add_abs(0)
        return st.f(x0)

    def tersect(left, right, func):
        while left <= right:
            lmid = left + (right - left) // 3
            rmid = right - (right - left) // 3
            (fl, fr) = (func(lmid), func(rmid))
            if fl < fr:
                (res, right) = (fl, rmid - 1)
            else:
                (res, left) = (fr, lmid + 1)
        return res
    print(tersect(-tot, tot, calc))
T = 1
for t in range(T):
    solve()