3540 - Ambuscada

From Bitnami MediaWiki

Cerința

N soldați, numerotați de la 1 la N, sunt prinși într-o ambuscadă. Asupra lor se execută M atacuri de tun. Atacurile afectează nu doar un soldat, ci un interval de soldați, provocând fiecăruia dintre aceștia o anumită pierdere (damage). De exemplu, atacul (3,7,5) afectează soldații 3,4,5,6,7 cu 5 damage. La început, toți soldații au V vieți. Câți soldați rămân în viață după cele M atacuri?

Date de intrare

Fișierul de intrare ambuscada.in conține pe prima linie numerele naturale N, M și V separate prin spații. Pe următoarele M linii se află câte 3 numere naturale i j k separate cu un spațiu, cu semnificația de mai sus.

Date de ieșire

Fișierul de ieșire ambuscada.out va conține un singur număr natural reprezentând numărul de soldați rămași în viață.

Restricții și precizări

  • 2 ≤ N ≤ 1.000.000.000, 1 ≤ M ≤ 100.000, 1 ≤ V ≤ 1.000.000.000
  • In toate testele, 1 ≤ i ≤ j ≤ N, 1 ≤ k ≤ V
  • Pentru teste în valoare de 30 de puncte, N<=100.000 și M<=50

Exemplul 1

ambuscada.in
6 4 10
2 5 2
1 3 7
2 6 3
3 5 6
ambuscada.out
2

Explicație

Inițial toți soldații aveau 10 vieți. După prima tragere: 10 8 8 8 8 10 După a doua tragere: 3 1 1 8 8 10 După a treia tragere: 3 0 0 5 5 7 După a patra tragere: 3 0 0 0 0 7 In final, 2 soldați au rămas în viață: primul și ultimul.

Exemplul 2

ambuscada.in
5 2
2 7 8
1
ambuscada.out
Date invalide: Linia 1 nu contine suficiente valori

Rezolvare

<syntaxhighlight lang="python" line>

  1. 3540 Ambuscada

def verificare_date_intrare(N, M, V, atacuri):

 # Verificăm dacă N, M și V sunt în intervalul specificat
 if not (2 <= N <= 1000000000 and 1 <= M <= 100000 and 1 <= V <= 1000000000):
   return False
 
 # Verificăm fiecare atac
 for atac in atacuri:
   i, j, k = atac
   # Verificăm dacă i, j și k sunt în intervalul specificat
   if not (1 <= i <= j <= N and 1 <= k <= V):
     return False
 
 return True

def soldati_ramasii(N, M, V, atacuri):

 # Inițializăm un vector cu viețile soldaților
 soldati = [V] * N
 
 # Parcurgem fiecare atac și actualizăm starea soldaților afectați
 for atac in atacuri:
   i, j, k = atac
   for index in range(i-1, j):
     soldati[index] -= k
 
 # Numărăm câți soldați au vieți pozitive și returnăm rezultatul
 soldati_ramas = sum(1 for viata in soldati if viata > 0)
 return soldati_ramas

def main():

 # Citim datele de intrare din fișier
 with open('ambuscada.in', 'r') as f:
   linii = f.readlines()
 
 # Verificăm dacă există suficiente linii în fișierul de intrare
 if len(linii) < 2:
   # Scriem mesaj de date invalide în fișierul de ieșire
   with open('ambuscada.out', 'w') as f:
     f.write("Date invalide: Nu sunt suficiente date in fisierul de intrare")
   return
 
 # Extragem N, M și V din prima linie
 try:
   N, M, V = map(int, linii[0].split())
 except ValueError:
   # Scriem mesaj de date invalide în fișierul de ieșire
   with open('ambuscada.out', 'w') as f:
     f.write("Date invalide: Linia 1 nu contine suficiente valori")
   return
 
 # Verificăm dacă există suficiente atacuri în fișierul de intrare
 if len(linii) - 1 < M:
   # Scriem mesaj de date invalide în fișierul de ieșire
   with open('ambuscada.out', 'w') as f:
     f.write("Date invalide: Nu sunt suficiente atacuri in fisierul de intrare")
   return
 
 # Citim atacurile
 atacuri = [tuple(map(int, line.split())) for line in linii[1:M+1]]
 
 # Verificăm datele de intrare
 if not verificare_date_intrare(N, M, V, atacuri):
   # Scriem mesaj de date invalide în fișierul de ieșire
   with open('ambuscada.out', 'w') as f:
     f.write("Datele de intrare sunt invalide")
   return
 
 # Calculăm numărul de soldați rămași în viață
 soldati_ramas = soldati_ramasii(N, M, V, atacuri)
 
 # Scriem rezultatul în fișierul de ieșire
 with open('ambuscada.out', 'w') as f:
   f.write(str(soldati_ramas))

if __name__ == "__main__":

 main()

</syntaxhighlight>