3133 – Arbori nr

From Bitnami MediaWiki

Cerința[edit | edit source]

Se dă un arbore cu n noduri şi rădăcina r, nodurile fiind etichetate cu numerele de la 1 la n. Se cere să se afle pentru fiecare nod i, câte noduri din subarborele cu rădăcina i au eticheta mai mică decât i.

Date de intrare[edit | edit source]

Fișierul de intrare arbori_nrIN.txt conține pe prima linie numerele n şi r, iar pe următoarele n-1 linii câte o pereche de numere u şi v, reprezentând faptul că între nodurile cu etichetele u şi v există o muchie.

Date de ieșire[edit | edit source]

Fișierul de ieșire arbori_nrOUT.txt va conține pe prima linie n numere naturale, al i-lea număr reprezentând numărul de noduri din subarborele cu eticheta i, ce au etichetele mai mici decât i.

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

  • 3 ≤ n ≤ 100.000
  • 1 ≤ u,v ≤ n, distincte

Exemplul 1[edit | edit source]

arbori_nrIN.txt:

5 2

2 3

5 4

5 1

2 5

arbori_nrOUT.txt:

0 1 0 0 2

Explicație:

În arbore 1,3,4 sunt frunze, deci au câte 0 noduri în subarborii cu rădăcinile 1, 3 respectiv 5, 2 are în subarbore nodul 1 cu eticheta mai mică decât 2, 5 are în subarbore două noduri cu etichetele mai mici decât 5, nodurile 1 şi 4.

Exemplul 2[edit | edit source]

arbori_nrIN.txt:

999999999 2

2 3

5 4

5 1

2 5

Output:

Error: n should be between 3 and 100000 (inclusive).

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3" line="1"> def validate_conditions(n):

   if not (3 <= n <= 100000):
       print("Error: n should be between 3 and 100000 (inclusive).")
       return False
   
   return True

def update(aib, pos, val):

   while pos <= len(aib):
       aib[pos] += val
       pos += pos & -pos

def query(aib, pos):

   sum_val = 0
   while pos > 0:
       sum_val += aib[pos]
       pos -= pos & -pos
   return sum_val

def dfs1(node, dad, G, aib, aiblant, rez, lant):

   update(aib, node, 1)
   update(aiblant, node, 1)
   rez[node] += query(aib, node - 1)
   for next_node in G[node]:
       if next_node != dad:
           dfs1(next_node, node, G, aib, aiblant, rez, lant)
   update(aiblant, node, -1)
   lant[node] = query(aiblant, node)

def dfs2(node, dad, G, aib, rez):

   update(aib, node, 1)
   rez[node] += query(aib, node - 1)
   for next_node in G[node][::-1]:
       if next_node != dad:
           dfs2(next_node, node, G, aib, rez)

def main():

   with open("arbori_nrIN.txt", "r") as f:
       n, r = map(int, f.readline().split())
       if not validate_conditions(n):
           return
       u, v = 0, 0  # Initialize u and v
       G = [[] for _ in range(n + 1)]
       rez = [0] * (n + 1)
       lant = [0] * (n + 1)
       aib = [0] * (4 * n + 1)
       aiblant = [0] * (4 * n + 1)
       for _ in range(n - 1):
           x, y = map(int, f.readline().split())
           G[x].append(y)
           G[y].append(x)
           # Update u and v based on the first edge
           if u == 0:
               u, v = x, y
   dfs1(r, 0, G, aib, aiblant, rez, lant)
   for i in range(4 * n):
       aib[i] = 0
   dfs2(r, 0, G, aib, rez)
   with open("arbori_nrOUT.txt", "w") as g:
       for i in range(1, n + 1):
           g.write(f"{i - rez[i] + lant[i] - 1} ")

if __name__ == "__main__":

   main()

</syntaxhighlight>