3705 - rectangles: Difference between revisions

From Bitnami MediaWiki
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Cerinta ==
== Cerinta ==


Să se calculeze restul împărțirii sumei ariilor dreptunghiurilor ce caracterizează toate rectangle-sequences din șir la numărul 1.000.000.007.
Se consideră un șir de <code>N</code> numere naturale. Numim rectangle-sequence orice secvență continuă din șir (formată din elemente situate pe poziții consecutive) care conține cel puțin două elemente. Fiecare rectangle-sequence este caracterizată de un dreptunghi cu lungimile laturilor egale cu cele mai mari două elemente din cadrul ei.


== Date de intrare ==
= Cerința =
Să se calculeze restul împărțirii sumei ariilor dreptunghiurilor ce caracterizează toate rectangle-sequences din șir la numărul <code>1.000.000.007</code>.


Prima linie contine numărul natural nenul N, reprezentând numărul elementelor din șir, iar linia a doua conține, separate prin câte un spațiu, cele N elemente. Întrucât volumul datelor de intrare este foarte mare, vă recomandăm, în cazul în care folosiți pentru citire biblioteca iostream din standardul C++, să adaugați la începutul funcției main urmatoarele instrucțiuni:
= Date de intrare =
Prima linie contine numărul natural nenul <code>N</code>, reprezentând numărul elementelor din șir, iar linia a doua conține, separate prin câte un spațiu, cele <code>N</code> elemente. Întrucât volumul datelor de intrare este foarte mare, vă recomandăm, în cazul în care folosiți pentru citire biblioteca <code>iostream</code> din standardul C++, să adaugați la începutul funcției <code>main</code> urmatoarele instrucțiuni:
std :: iosbase :: sync_with_stdio (false);
std :: cin.tie(0);


*std :: iosbase :: sync_with_stdio (false);
= Date de ieșire =
*std :: cin.tie(0);
Ieșirea conține numărul de determinat, modulo <code>1.000.000.007</code>. În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".


== Date de iesire ==
= Restricții și precizări =


Ieșirea conține numărul de determinat, modulo 1.000.000.007.
* <code>1 ≤ n ≤ 1.000.000</code>
* <code>1 ≤ orice element din șir 1 ≤ 1.000.000.000</code>
* Subtask 1 (13 puncte): <code>N ≤ 2000</code>
* Subtask 2 (23 puncte): <code>N ≤ 100.000</code> și există cel mult <code>100</code> de numere distincte în șir.
* Subtask 3 (27 puncte): <code>N ≤ 200.000</code>
* Subtask 4 (37 puncte): nu există restricții suplimentare


== Restrictii si precizari
= Exemplul 1: =
Intrare
3
2 3 1
Ieșire
15


*1 ≤ n ≤ 1.000.000
=== Explicație ===
*1 ≤ orice element din șir 1 ≤ 1.000.000.000
Sunt <code>3</code> rectangle-sequences: <code>(2; 3)</code>; <code>(2; 3; 1)</code>; <code>(3; 1)</code>. Ariile celor trei deptunghiuri ce le caracterizează sunt: <code>6</code>, <code>6</code>, <code>3</code>.
*Subtask 1 (13 puncte): N ≤ 2000
*Subtask 2 (23 puncte): N ≤ 100.000 și există cel mult 100 de numere distincte în șir.
*Subtask 3 (27 puncte): N ≤ 200.000
*Subtask 4 (37 puncte): nu există restricții suplimentare


== Exemplul 1 ==
== Exemplul 2: ==
 
Intrare
; intrare
100000000000
 
2 3 1
:3
Ieșire
:2 3 1
Datele nu corespund restrictiilor impuse
 
; iesire
 
:Datele introduse corespund restrictiilor impuse.
 
:15
 
==Exemplul 2 ==
 
; intrare
 
:4
:3 1 2
 
; iesire
 
:Datele nu corespund restrictiilor impuse.


== Rezolvare ==  
== Rezolvare ==  
<syntaxhighlightlang="python3"line="1">
<syntaxhighlight lang="python3" line="1">
MaxN = 1000010
mod = 10**9 + 7


def rest_suma_arii_rectangle_sequences(arr):
v = [0] * MaxN
    mod = 1000000007
left1 = [0] * MaxN
    n = len(arr)
left2 = [0] * MaxN
right1 = [0] * MaxN
right2 = [0] * MaxN


    stack = []
def multiply(a, b, c, d):
     suma_arii = 0
     return ((a * b) % mod) * ((c * d) % mod) % mod


     for i in range(n):
def citeste_si_verifica_elemente(n):
         while stack and arr[i] >= arr[stack[-1]]:
    print(f"Introduceți {n} elemente (fiecare urmat de Enter):")
             h = arr[stack.pop()]
    v_temp = []
             w = i if not stack else i - stack[-1] - 1
     for i in range(1, n + 1):
             suma_arii = (suma_arii + h * w) % mod
         try:
         stack.append(i)
             x = int(input(f"Elementul {i}: "))
             if not (1 <= x <= 10**9):
                print("Datele nu corespund restricțiilor impuse")
                return None
             v_temp.append(x)
         except ValueError:
            print("Datele nu corespund restricțiilor impuse")
            return None
    return v_temp


     while stack:
def main():
         h = arr[stack.pop()]
     try:
         w = n if not stack else n - stack[-1] - 1
         n = int(input("Introduceți lungimea șirului: "))
         suma_arii = (suma_arii + h * w) % mod
         if not (1 <= n <= 10**6):
            print("Datele nu corespund restricțiilor impuse")
            return
    except ValueError:
        print("Datele nu corespund restricțiilor impuse")
         return
   
    v_input = citeste_si_verifica_elemente(n)
    if v_input is None:
        return
   
    v[1:n+1] = v_input


     return suma_arii
     for i in range(1, n+1):
        left1[i] = left2[i] = 0
        right1[i] = right2[i] = n + 1
   
    st1, st2, aux = [], [], []
    for i in range(1, n+1):
        while st2 and v[i] > v[st2[-1]]:
            right2[st2[-1]] = i
            st2.pop()
        while st1 and v[i] > v[st1[-1]]:
            right1[st1[-1]] = i
            aux.append(st1.pop())
        st1.append(i)
        while aux:
            st2.append(aux.pop())
   
    st1.clear()
    st2.clear()
   
    for i in range(n, 0, -1):
        while st2 and v[i] >= v[st2[-1]]:
            left2[st2[-1]] = i
            st2.pop()
        while st1 and v[i] >= v[st1[-1]]:
            left1[st1[-1]] = i
            aux.append(st1.pop())
        st1.append(i)
        while aux:
            st2.append(aux.pop())
   
    sol = 0
    for i in range(1, n+1):
        if left1[i] > 0:
            a = left1[i] - left2[i]
            b = right1[i] - i
            sol += multiply(a, b, v[i], v[left1[i]])
        if right1[i] < n + 1:
            a = i - left1[i]
            b = right2[i] - right1[i]
            sol += multiply(a, b, v[i], v[right1[i]])
   
    sol %= mod
    print(sol)


# Exemplu de folosire
if __name__ == "__main__":
sir = [2, 5, 1, 4, 6, 3]
    main()
rezultat = rest_suma_arii_rectangle_sequences(sir)
print("Restul împărțirii sumei ariilor la 1.000.000.007 este:", rezultat)


</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 22:15, 22 March 2024

Cerinta[edit | edit source]

Se consideră un șir de N numere naturale. Numim rectangle-sequence orice secvență continuă din șir (formată din elemente situate pe poziții consecutive) care conține cel puțin două elemente. Fiecare rectangle-sequence este caracterizată de un dreptunghi cu lungimile laturilor egale cu cele mai mari două elemente din cadrul ei.

Cerința[edit | edit source]

Să se calculeze restul împărțirii sumei ariilor dreptunghiurilor ce caracterizează toate rectangle-sequences din șir la numărul 1.000.000.007.

Date de intrare[edit | edit source]

Prima linie contine numărul natural nenul N, reprezentând numărul elementelor din șir, iar linia a doua conține, separate prin câte un spațiu, cele N elemente. Întrucât volumul datelor de intrare este foarte mare, vă recomandăm, în cazul în care folosiți pentru citire biblioteca iostream din standardul C++, să adaugați la începutul funcției main urmatoarele instrucțiuni:

std :: iosbase :: sync_with_stdio (false);
std :: cin.tie(0);

Date de ieșire[edit | edit source]

Ieșirea conține numărul de determinat, modulo 1.000.000.007. În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".

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

  • 1 ≤ n ≤ 1.000.000
  • 1 ≤ orice element din șir 1 ≤ 1.000.000.000
  • Subtask 1 (13 puncte): N ≤ 2000
  • Subtask 2 (23 puncte): N ≤ 100.000 și există cel mult 100 de numere distincte în șir.
  • Subtask 3 (27 puncte): N ≤ 200.000
  • Subtask 4 (37 puncte): nu există restricții suplimentare

Exemplul 1:[edit | edit source]

Intrare

3
2 3 1

Ieșire

15

Explicație[edit | edit source]

Sunt 3 rectangle-sequences: (2; 3); (2; 3; 1); (3; 1). Ariile celor trei deptunghiuri ce le caracterizează sunt: 6, 6, 3.

Exemplul 2:[edit | edit source]

Intrare

100000000000
2 3 1

Ieșire

Datele nu corespund restrictiilor impuse

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3" line="1"> MaxN = 1000010 mod = 10**9 + 7

v = [0] * MaxN left1 = [0] * MaxN left2 = [0] * MaxN right1 = [0] * MaxN right2 = [0] * MaxN

def multiply(a, b, c, d):

   return ((a * b) % mod) * ((c * d) % mod) % mod

def citeste_si_verifica_elemente(n):

   print(f"Introduceți {n} elemente (fiecare urmat de Enter):")
   v_temp = []
   for i in range(1, n + 1):
       try:
           x = int(input(f"Elementul {i}: "))
           if not (1 <= x <= 10**9):
               print("Datele nu corespund restricțiilor impuse")
               return None
           v_temp.append(x)
       except ValueError:
           print("Datele nu corespund restricțiilor impuse")
           return None
   return v_temp

def main():

   try:
       n = int(input("Introduceți lungimea șirului: "))
       if not (1 <= n <= 10**6):
           print("Datele nu corespund restricțiilor impuse")
           return
   except ValueError:
       print("Datele nu corespund restricțiilor impuse")
       return
   
   v_input = citeste_si_verifica_elemente(n)
   if v_input is None:
       return
   
   v[1:n+1] = v_input
   for i in range(1, n+1):
       left1[i] = left2[i] = 0
       right1[i] = right2[i] = n + 1
   
   st1, st2, aux = [], [], []
   for i in range(1, n+1):
       while st2 and v[i] > v[st2[-1]]:
           right2[st2[-1]] = i
           st2.pop()
       while st1 and v[i] > v[st1[-1]]:
           right1[st1[-1]] = i
           aux.append(st1.pop())
       st1.append(i)
       while aux:
           st2.append(aux.pop())
   
   st1.clear()
   st2.clear()
   
   for i in range(n, 0, -1):
       while st2 and v[i] >= v[st2[-1]]:
           left2[st2[-1]] = i
           st2.pop()
       while st1 and v[i] >= v[st1[-1]]:
           left1[st1[-1]] = i
           aux.append(st1.pop())
       st1.append(i)
       while aux:
           st2.append(aux.pop())
   
   sol = 0
   for i in range(1, n+1):
       if left1[i] > 0:
           a = left1[i] - left2[i]
           b = right1[i] - i
           sol += multiply(a, b, v[i], v[left1[i]])
       if right1[i] < n + 1:
           a = i - left1[i]
           b = right2[i] - right1[i]
           sol += multiply(a, b, v[i], v[right1[i]])
   
   sol %= mod
   print(sol)

if __name__ == "__main__":

   main()

</syntaxhighlight>