Sunteți pe pagina 1din 2

Subsir crescator maximal

Fie un vector a cu N elemente. Numim subsir al lui a de lungime K un vector a' =(ai1, ai2, ..., aiK) astfel incat
sa avem i1 < i2 < ... < iK.

Cerinta
Sa se determine un subsir al lui a care este ordonat strict crescator si care are lungimea maxima.

Date de intrare
Fisierul de intrare scmax.in contine pe prima linie numarul N reprezentand numarul de elemente ale
vectorului a . Pe cea de-a doua linie se afla N numere naturale reprezentand elementele vectorului a.

Date de iesire
In fisierul de iesire scmax.out se va afisa pe prima linie Lmax, lungimea celui mai lung subsir crescator al
sirului a. Pe cea de-a doua linie se vor afla Lmax numere naturale reprezentand cel mai lung subsir crescator al
vectorului a. Daca exista mai multe solutii se poate afisa oricare.

Restrictii
1 N 100 000
1 ai 2 000 000 000, pentru orice i de la 1 la N
Se acorda 50% din punctaj daca este afisata corect doar lungimea celui mai lung subsir crescator

Exemplu
scmax.in
5

24 12 15 15 19

12 15 19

Indicatii de rezolvare
O prima rezolvare utilizeaza programarea dinamica. Se noteaza besti - lungimea maxima a unui subsir
crescator care se termina pe pozitia i . Obtinem astfel urmatoarea relatie de recurenta: besti = 1
+ max(bestj) cu 1 j < i si aj < ai . Pentru a reconstrui solutia mai retinem un vector cu semnificatia prei pozitia valorii care preceda elementul i in subsirul crescator care se termina pe pozitia i. Aceasta solutie are
complexitatea O(N2) si obtine 70 de puncte.
Complexitatea optima este O(N*log2N). La fiecare pas i trebuie determinata lungimea cea mai
mare bestj unde 1 j < i astfel incat aj ai. Pentru a afla aceasta informatie in timp optim O(log2N) se
poate folosi un arbore de intervale sau un arbore indexat binar.
Rezolvare:

// Subsir crescator maximal - complexitate O (nlogn) - cu cautare

binara
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
int n, a[100010], minim[100010], poz[100010], sol, v[100010], nv;
// minim[i] = valoarea minima cu care se poate termina un subsir de lungime
i
// poz[i] = pozitia din vectorul minim gasita in urma cautarii binare
pentru elementul a[i]
inline void Read()
{
ifstream f("scmax.in");
f>>n;
int i;
for (i=1; i<=n; i++)

f>>a[i];
f.close();

inline void Solve()


{
int i, p;
for (i=1; i<=n; i++)
{
p = upper_bound(minim+1, minim+sol+1, a[i]) - minim;
if (minim[p-1] == a[i])
p--;
minim[p] = a[i];
poz[i] = p;
if (p>sol)
sol = p;
}
}
inline void Write()
{
ofstream g("scmax.out");
g<<sol<<"\n";
int i, lg = sol;
for (i=n; i; i--)
{
if (poz[i] == lg)
{
v[++nv] = a[i];
lg--;
}
}
for (i=nv; i; i--)
g<<v[i]<<" ";
g<<"\n";
g.close();
}
int main()
{
Read();
Solve();
Write();
return 0;
}

S-ar putea să vă placă și