1901 - Median Heaps: Difference between revisions

From Bitnami MediaWiki
Pagină nouă: == Cerința == Se dă un vector de N numere naturale nenule, indexat de la 1. <br> Se cere să se raspundă la Q interogări de tipul: *pentru un interval [l, r] din vector, aflați costul total mimin, al egalizării tuturor elementelor din interval. Într-un interval [l, r], puteți crește sau micșora fiecare element cu costul x unde x este diferența dintre valoarea nouă și valoarea inițială. Costul total este suma acestor costuri. == Date de intrare == *pe prima lini...
 
No edit summary
 
Line 1: Line 1:
== Cerința ==
= Cerința =
Se dă un vector de N numere naturale nenule, indexat de la 1.
Se dă un vector de <code>N</code> numere naturale nenule, indexat de la <code>1</code>.
<br>
 
Se cere să se raspundă la Q interogări de tipul:
Se cere să se raspundă la <code>Q</code> interogări de tipul:
*pentru un interval [l, r] din vector, aflați costul total mimin, al egalizării tuturor elementelor din interval.
 
Într-un interval [l, r], puteți crește sau micșora fiecare element cu costul x unde x este diferența dintre valoarea nouă și valoarea inițială. Costul total este suma acestor costuri.
* pentru un interval <code>[l, r]</code> din vector, aflați costul total mimin, al egalizării tuturor elementelor din interval.
== Date de intrare ==
 
*pe prima linie numărul N.
Într-un interval <code>[l, r]</code>, puteți crește sau micșora fiecare element cu costul <code>x</code> unde <code>x</code> este diferența dintre valoarea nouă și valoarea inițială. Costul total este suma acestor costuri.
*pe a doua linie N numere naturale nenule : x1 ,x2 , … xN.
 
*pe a treia linie numărul Q.
= Date de intrare =
*pe următoarele Q linii 2 numere: l, r.
 
== Date de ieșire ==  
* pe prima linie numărul <code>N</code>.
Se vor afișa Q numere pe fiecare linie, reprezentând constul total minim, al fiecărui interval l r.
* pe a doua linie <code>N</code> numere naturale nenule : , , … .
== Restricții și precizări ==
* pe a treia linie numărul <code>Q</code>.
*'''1 ≤ N, Q ≤ 100.000'''
* pe următoarele <code>Q</code> linii <code>2</code> numere: <code>l, r</code>.
*'''1 ≤ l ≤ r ≤ 100.000'''
 
*'''1 ≤ xi ≤ 1.000.000.000'''
= Date de ieșire =
== Exemplul 1 ==
Se vor afișa <code>Q</code> numere pe fiecare linie, reprezentând constul total minim, al fiecărui interval <code>l r</code>.
; Intrare
 
: 9
= Restricții și precizări =
: 3 2 16 15 12 6 20 4 5
 
: 3
* <code>1 ≤ N, Q ≤ 100.000</code>
: 2 7
* <code>1 ≤ l ≤ r ≤ 100.000</code>
: 2 2
* <code>1 ≤</code>  <code>≤ 1.000.000.000</code>
: 3 8
 
; Ieșire
= Exemplu: =
: 31
Intrare
: 0
9
: 29
3 2 16 15 12 6 20 4 5
<br>
3
== Exemplul 2 ==
2 7
; Intare
2 2
: 5
3 8
: 1 2 3 4 5
Ieșire
: 2
31
: 1 4
0
: 3 5
29
; Ieșire
 
: 9
= Explicație =
: 6
Pentru intervalul <code>[2, 7]</code>, costul total minim este <code>31</code>, deoarece egalizăm fiecare număr din interval cu <code>12</code>.
<br>
 
Pentru intervalul <code>[2, 2]</code>, costul total minim este <code>0</code>, deoarece avem un singur element în interval.
 
Pentru intervalul <code>[3, 8]</code>, costul total minim este <code>29</code>, deoarece egalizăm fiecare număr din interval cu <code>12</code>
 
== Rezolvare ==  
== Rezolvare ==  
<syntaxhighlight lang="python" line>
<syntaxhighlight lang="python" line="1">
#1901 - Median Heaps
import math
def is_valid_input(N, Q, x_values, queries):
 
     if not (1 <= N <= 100000 and 1 <= Q <= 100000):
Nmax = 100001
         return False
 
    if not all(1 <= xi <= 1000000000 for xi in x_values):
class Query:
        return False
    def __init__(self, st, dr, pos):
     if not all(1 <= l <= r <= N for l, r in queries):
        self.st = st
        self.dr = dr
        self.pos = pos
 
def update(aib, aibs, pos, val1, val2):
    while pos < Nmax:
        aib[pos] += val1
        aibs[pos] += val2
        pos += pos & -pos
 
def query(aib, aibs, pos, c):
     sum_val = 0
    s = 0
    while pos > 0:
        sum_val += aib[pos]
        if aibs is not None:
            s += aibs[pos]
        pos -= pos & -pos
    return sum_val if c == 1 else s
 
def add(k, N, V, S, aib, aibs):
    update(aib, aibs, N[k], 1, V[S[N[k]]])
 
def delete(k, N, V, S, aib, aibs):
    update(aib, aibs, N[k], -1, -V[S[N[k]]])
 
def binary_search(pos, n, aib):
    st, dr = 1, n
    ans = -1
    while st <= dr:
         mid = (st + dr) // 2
        q = query(aib, None, mid, 1)
        if q >= pos:
            dr = mid - 1
            ans = mid
        else:
            st = mid + 1
    return ans
 
def verify_restrictions(n, q, ranges):
     if not (1 <= n <= 100000 and 1 <= q <= 100000):
         return False
         return False
    for l, r in ranges:
        if not (1 <= l <= r <= 100000):
            return False
     return True
     return True


def main():
    n = int(input())
    V = [0] * (n + 1)
   
    values = list(map(int, input().split()))
    for i in range(1, n + 1):
        V[i] = values[i-1]
   
    q = int(input())
    ranges = []
    Q = []
    for i in range(1, q + 1):
        st, dr = map(int, input().split())
        ranges.append((st, dr))
        Q.append(Query(st, dr, i))
    if not verify_restrictions(n, q, ranges):
        print("Datele nu corespund restrictiilor impuse")
        return
    block = int(math.sqrt(n))
    S = list(range(n + 1))
    S[1:] = sorted(S[1:], key=lambda x: V[x])
    N = [0] * (n + 1)
    for i in range(1, n + 1):
        N[S[i]] = i


def minimize_costs(N, x_values, Q, queries):
    Q.sort(key=lambda x: (x.dr // block, x.st if x.dr // block % 2 == 0 else -x.st))
     result = []
     aib = [0] * Nmax
     for l, r in queries:
    aibs = [0] * Nmax
         interval = x_values[l - 1:r]
    Rez = [0] * (q + 1)
         min_value = min(interval)
   
         cost = sum(min_value - xi for xi in interval)
    st, dr = 1, 0
         result.append(cost)
     for i in range(1, q + 1):
    return result
         s, d = Q[i-1].st, Q[i-1].dr
        while st < s:
            delete(st, N, V, S, aib, aibs)
            st += 1
         while st > s:
            st -= 1
            add(st, N, V, S, aib, aibs)
         while dr < d:
            dr += 1
            add(dr, N, V, S, aib, aibs)
         while dr > d:
            delete(dr, N, V, S, aib, aibs)
            dr -= 1


        poss = (d - s + 2) // 2
        ans = binary_search(poss, n, aib)
        s1 = query(aib, aibs, n, 2)
        h1 = query(aib, None, n, 1)
        s2 = query(aib, aibs, ans, 2)
        h2 = query(aib, None, ans, 1)
        s1 -= s2
        h1 -= h2


if __name__ == "__main__":
         Rez[Q[i-1].pos] = s1 - h1 * V[S[ans]] + (-s2 + h2 * V[S[ans]])
    try:
         # Citire date de intrare
        N = int(input())
        x_values = list(map(int, input().split()))
        Q = int(input())
        queries = [tuple(map(int, input().split())) for _ in range(Q)]


        # Verificare restricții
    for i in range(1, q + 1):
        if not is_valid_input(N, Q, x_values, queries):
         print(Rez[i])
            print("Fals")
         else:
            # Calcul și afișare rezultate
            results = minimize_costs(N, x_values, Q, queries)
            for result in results:
                print(result)


    except ValueError:
if __name__ == "__main__":
        print("Fals")
    main()


</syntaxhighlight>
</syntaxhighlight>
== Explicatie ==
Pentru intervalul [2, 7], costul total minim este 31, deoarece egalizăm fiecare număr din interval cu 12.
<br>
Pentru intervalul [2, 2], costul total minim este 0, deoarece avem un singur element în interval.
<br>
Pentru intervalul [3, 8], costul total minim este 29, deoarece egalizăm fiecare număr din interval cu 12.

Latest revision as of 13:50, 18 May 2024

Cerința[edit | edit source]

Se dă un vector de N numere naturale nenule, indexat de la 1.

Se cere să se raspundă la Q interogări de tipul:

  • pentru un interval [l, r] din vector, aflați costul total mimin, al egalizării tuturor elementelor din interval.

Într-un interval [l, r], puteți crește sau micșora fiecare element cu costul x unde x este diferența dintre valoarea nouă și valoarea inițială. Costul total este suma acestor costuri.

Date de intrare[edit | edit source]

  • pe prima linie numărul N.
  • pe a doua linie N numere naturale nenule : , , … .
  • pe a treia linie numărul Q.
  • pe următoarele Q linii 2 numere: l, r.

Date de ieșire[edit | edit source]

Se vor afișa Q numere pe fiecare linie, reprezentând constul total minim, al fiecărui interval l r.

Restricții și precizări[edit | edit source]

  • 1 ≤ N, Q ≤ 100.000
  • 1 ≤ l ≤ r ≤ 100.000
  • 1 ≤  ≤ 1.000.000.000

Exemplu:[edit | edit source]

Intrare

9
3 2 16 15 12 6 20 4 5
3
2 7
2 2
3 8

Ieșire

31
0
29

Explicație[edit | edit source]

Pentru intervalul [2, 7], costul total minim este 31, deoarece egalizăm fiecare număr din interval cu 12.

Pentru intervalul [2, 2], costul total minim este 0, deoarece avem un singur element în interval.

Pentru intervalul [3, 8], costul total minim este 29, deoarece egalizăm fiecare număr din interval cu 12

Rezolvare[edit | edit source]

<syntaxhighlight lang="python" line="1"> import math

Nmax = 100001

class Query:

   def __init__(self, st, dr, pos):
       self.st = st
       self.dr = dr
       self.pos = pos

def update(aib, aibs, pos, val1, val2):

   while pos < Nmax:
       aib[pos] += val1
       aibs[pos] += val2
       pos += pos & -pos

def query(aib, aibs, pos, c):

   sum_val = 0
   s = 0
   while pos > 0:
       sum_val += aib[pos]
       if aibs is not None:
           s += aibs[pos]
       pos -= pos & -pos
   return sum_val if c == 1 else s

def add(k, N, V, S, aib, aibs):

   update(aib, aibs, N[k], 1, V[S[N[k]]])

def delete(k, N, V, S, aib, aibs):

   update(aib, aibs, N[k], -1, -V[S[N[k]]])

def binary_search(pos, n, aib):

   st, dr = 1, n
   ans = -1
   while st <= dr:
       mid = (st + dr) // 2
       q = query(aib, None, mid, 1)
       if q >= pos:
           dr = mid - 1
           ans = mid
       else:
           st = mid + 1
   return ans

def verify_restrictions(n, q, ranges):

   if not (1 <= n <= 100000 and 1 <= q <= 100000):
       return False
   for l, r in ranges:
       if not (1 <= l <= r <= 100000):
           return False
   return True

def main():

   n = int(input())
   V = [0] * (n + 1)
   
   values = list(map(int, input().split()))
   for i in range(1, n + 1):
       V[i] = values[i-1]
   
   q = int(input())
   ranges = []
   Q = []
   for i in range(1, q + 1):
       st, dr = map(int, input().split())
       ranges.append((st, dr))
       Q.append(Query(st, dr, i))
   if not verify_restrictions(n, q, ranges):
       print("Datele nu corespund restrictiilor impuse")
       return
   block = int(math.sqrt(n))
   S = list(range(n + 1))
   S[1:] = sorted(S[1:], key=lambda x: V[x])
   N = [0] * (n + 1)
   for i in range(1, n + 1):
       N[S[i]] = i
   Q.sort(key=lambda x: (x.dr // block, x.st if x.dr // block % 2 == 0 else -x.st))
   aib = [0] * Nmax
   aibs = [0] * Nmax
   Rez = [0] * (q + 1)
   
   st, dr = 1, 0
   for i in range(1, q + 1):
       s, d = Q[i-1].st, Q[i-1].dr
       while st < s:
           delete(st, N, V, S, aib, aibs)
           st += 1
       while st > s:
           st -= 1
           add(st, N, V, S, aib, aibs)
       while dr < d:
           dr += 1
           add(dr, N, V, S, aib, aibs)
       while dr > d:
           delete(dr, N, V, S, aib, aibs)
           dr -= 1
       poss = (d - s + 2) // 2
       ans = binary_search(poss, n, aib)
       s1 = query(aib, aibs, n, 2)
       h1 = query(aib, None, n, 1)
       s2 = query(aib, aibs, ans, 2)
       h2 = query(aib, None, ans, 1)
       s1 -= s2
       h1 -= h2
       Rez[Q[i-1].pos] = s1 - h1 * V[S[ans]] + (-s2 + h2 * V[S[ans]])
   for i in range(1, q + 1):
       print(Rez[i])

if __name__ == "__main__":

   main()

</syntaxhighlight>