Clasa a XII-a · Tehnici avansate: doi pointeri, căutare binară pe răspuns, stive monotoneRead in English
Stiva monotonă — următorul element mai mare în C++
În engleză: Monotonic stack: the next greater element
Ideea
Pentru fiecare a[i] căutăm prima valoare strict mai mare aflată în dreapta lui (sau -1). Ținem o stivă cu pozițiile care încă „așteaptă” un element mai mare; valorile lor sunt descrescătoare de la bază spre vârf. Când vine a[i], toate pozițiile din vârf cu valoare mai mică și-au găsit răspunsul: îl notăm și le scoatem. Apoi punem i în stivă. Pozițiile rămase la final nu au un element mai mare. Fiecare poziție intră și iese din stivă cel mult o dată.
Descrierea în engleză
For every a[i] we look for the first strictly greater value to its right (or -1). We keep a stack with the positions still 'waiting' for a greater element; their values decrease from the bottom to the top. When a[i] arrives, all positions on top with a smaller value have found their answer: we record it and pop them. Then we push i. The positions left at the end have no greater element. Every position is pushed and popped at most once.
- Complexitate
- O(n)
- Clasa
- Clasa a XII-a (Grade 12)
Exemple
Intrare
8 4 5 2 25 7 8 1 9
Ieșire așteptată
5 25 25 -1 8 9 9 -1
Intrare
4 5 5 3 1
Ieșire așteptată
-1 -1 -1 -1
Codul C++
Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.
/*
* Titlu: Stiva monotonă — următorul element mai mare
* Clasa: 12
* Capitol: Tehnici avansate: doi pointeri, căutare binară pe răspuns, stive monotone
* Descriere: Pentru fiecare a[i] căutăm prima valoare strict mai mare aflată în
* dreapta lui (sau -1). Ținem o stivă cu pozițiile care încă „așteaptă”
* un element mai mare; valorile lor sunt descrescătoare de la bază spre
* vârf. Când vine a[i], toate pozițiile din vârf cu valoare mai mică
* și-au găsit răspunsul: îl notăm și le scoatem. Apoi punem i în stivă.
* Pozițiile rămase la final nu au un element mai mare. Fiecare poziție
* intră și iese din stivă cel mult o dată.
* Complexitate: O(n)
*
* Exemplu
* Intrare:
* 8
* 4 5 2 25 7 8 1 9
* Ieșire: 5 25 25 -1 8 9 9 -1
*
* Exemplu
* Intrare:
* 4
* 5 5 3 1
* Ieșire: -1 -1 -1 -1
*/
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<long long> a(n), rasp(n, -1);
for (int i = 0; i < n; i++)
cin >> a[i];
stack<int> st; // poziții, cu valori descrescătoare spre vârf
for (int i = 0; i < n; i++)
{
while (!st.empty() && a[st.top()] < a[i])
{
rasp[st.top()] = a[i];
st.pop();
}
st.push(i);
}
for (int i = 0; i < n; i++)
cout << rasp[i] << (i + 1 < n ? ' ' : '\n');
return 0;
}
Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.