3759 - Cartita

De la Universitas MediaWiki

Enunt

În grădina lui Macarie există un șir de N morcovi, numerotați de la 1 la N. Ca să știe unde sunt plantați, Macarie a făcut câte o grămăjoară de pământ în dreptul fiecărui morcov și a notat înălțimea fiecăreia exprimată în centimetri. Astfel morcovul i are în dreptul său o grămăjoară de pământ cu înălțimea de h[i] centimetri.

O cârtiță neastâmpărată sapă galerii subterane pe sub morcovii lui Macarie. Când sapă o galerie către un morcov, tot pământul rezultat îl scoate afară modificând astfel înălțimea grămăjoarei corespunzătoare acelui morcov, dar și ale celorlalți morcovi din grădină.

Dacă în urma săpării unei galerii către morcovul de pe poziția pos înălțimea grămăjoarei lui a crescut cu x centimetri, atunci înălțimile grămăjoarelor tuturor morcovilor se modifică după următoarea regulă ce depinde de un număr K:

  • înălțimea grămăjoarei morcovului pos - 1 se modifică cu x - K centimetri iar a morcovului pos + 1 cu x + K centimetri,
  • înălțimile gramăjoarelor morcovilor pos - 2 și pos + 2 se modifică cu x - 2 * K respectiv x + 2 * K centimetri
  • În caz general, înălțimea se modifică după următoarele reguli pentru fiecare morcov din grădină:

- Înălțimea h[pos - i] devine h[pos - i] + x - i * K, pentru fiecare i, 1 ≤ i ≤ pos-1 - Înălțimea h[pos + i] devine h[pos + i] + x + i * K, pentru fiecare i, 1 ≤ i ≤ N-pos

Cerinţa

Se cunosc înălțimile inițiale ale tuturor celor N grămăjoare și cele U modificări făcute de cârtiță asupra înălțimilor grămăjoarelor de pământ ale morcovilor. Știm că în cadrul unei secvențe continue de morcovi cel mai tentant pentru cârtiță este morcovul cu cea mai mică înălțime a grămăjoarei de pământ. Ajutați-l pe Macarie să identifice înălțimea grămăjoarei celui mai tentant morcov, pentru mai multe intervale date, după efectuarea tuturor modificărilor realizate de cârtiță.

Date de intrare

Fișierul de intrare cartita.in conţine pe prima linie un număr natural N având semnificația din enunț.

Pe următoarea linie se află N numere naturale despărțite prin câte un spațiu, reprezentând în ordine, înălțimile grămăjoarelor de pământ, al i-lea număr reprezentând înălțimea inițială h[i], a grămăjoarei din dreptul morcovului i.

Pe a treia linie se află un număr natural U reprezentând numărul de morcovi către care cărtița a săpat galerii.

Pe următoarele U linii se află câte un triplet de numere naturale pos, x, K, separate între ele prin câte un spațiu, cu semnificația că în urma săpării unei galerii către morcovul pos înălțimea grămăjoarei lui a crescut cu x centimetri, iar celelalte înălțimi se modifică, după regula descrisă în enunț.

Pe următoarea linie se găsește numărul Q reprezentând numărul de intervale unde se dorește identificarea înălțimii minime a unei grămăjoare corespunzătoare celui mai tentant morcov.

Pe următoarele Q linii sunt câte două numere naturale L, R, separate între ele printr-un spațiu, reprezentând capetele intervalului de morcovi investigat.

Date de ieșire

Fişierul de ieşire cartita.out va conţine Q linii, pe fiecare găsindu-se, în ordine, răspunsul la intervalele investigate.

Restricţii şi precizări

  • 1 ≤ N ≤ 100.000
  • 1 ≤ U ≤ 300.000
  • 1 ≤ Q ≤ 200.000
  • 1 ≤ L ≤ R ≤ N
  • Inițial 1 ≤ h[i] ≤ N, pentru fiecare i, 1 ≤ i ≤ N
  • 1 ≤ pos ≤ N, 1 ≤ x ≤ 400 și -21 ≤ K ≤ 21, K ≠ 0

Exemplu

cartita.in
6
1 6 2 4 3 4
3
4 5 2
2 4 1
4 2 8
3
1 6
2 4
4 4
cartita.in
-19
-3
17


Explicație

  • După prima galerie săpată către morcovul 4, șirul înălțimilor celor N=6 grămăjoare a devenit (0, 7, 5, 9, 10, 13).
  • După a doua galerie săpată către morcovul 2, șirul înălțimilor celor N=6 grămăjoare a devenit (3, 11, 10, 15, 17, 21).
  • După a treia galerie săpată către morcovul 4, șirul înălțimilor celor N=6 grămăjoare a devenit (-19, -3, 4, 17, 27, 39)
  • Pe intervalul [1,6], înălțimea minimă este -19, pe intervalul [2,4], înălțimea minimă este -3, iar pentru ultimul interval investigat [4,4] înălțimea minimă este 17.

Rezolvare

from math import inf

class SegmentTree:
    def __init__(self, arr):
        self.n = len(arr)
        self.tree = [0] * (4 * self.n)
        self.construct_segment_tree(arr, 0, self.n - 1, 0)
    
    def construct_segment_tree(self, arr, start, end, idx):
        if start == end:
            self.tree[idx] = arr[start]
            return
        mid = (start + end) // 2
        self.construct_segment_tree(arr, start, mid, 2 * idx + 1)
        self.construct_segment_tree(arr, mid + 1, end, 2 * idx + 2)
        self.tree[idx] = min(self.tree[2 * idx + 1], self.tree[2 * idx + 2])
    
    def update(self, pos, val, start, end, idx):
        if start == end:
            self.tree[idx] += val
            return
        mid = (start + end) // 2
        if pos <= mid:
            self.update(pos, val, start, mid, 2 * idx + 1)
        else:
            self.update(pos, val, mid + 1, end, 2 * idx + 2)
        self.tree[idx] = min(self.tree[2 * idx + 1], self.tree[2 * idx + 2])
    
    def query(self, left, right, start, end, idx):
        if left > end or right < start:
            return inf
        if left <= start and right >= end:
            return self.tree[idx]
        mid = (start + end) // 2
        return min(self.query(left, right, start, mid, 2 * idx + 1),
                   self.query(left, right, mid + 1, end, 2 * idx + 2))

def main():
    N = int(input())
    heights = list(map(int, input().split()))
    U = int(input())
    changes = []
    for _ in range(U):
        pos, x, K = map(int, input().split())
        changes.append((pos, x, K))

    tree = SegmentTree(heights)
    
    Q = int(input())
    for _ in range(Q):
        L, R = map(int, input().split())
        min_height = inf
        for pos, x, K in changes:
            min_height = min(min_height, tree.query(L - 1, R - 1, 0, N - 1, 0) + x - abs(L - pos) * K)
        print(min_height)

if __name__ == "__main__":
    main()