Pagini recente » Cod sursa (job #3321230) | Cod sursa (job #792506) | Cod sursa (job #3321348) | Cod sursa (job #3330339) | Cod sursa (job #3339452)
#include <fstream>
#define DIM 100010
using namespace std;
/* LIS
mentinem pentru fiecare lungime L cea mai mica valore posibila cu care se poate
termina un subsir crescator de lungime L, folosind elementele parcurse pana acum
pentru a putea reconstrui o solutie, retinem parintele fiecarui element folosit
aici nu se tin minte direct valorile, ci indicii in v
d[len] = indicele din v al elementului care reprezinta "cel mai bun capat"
(valoarea minima) pentru un subsir crescator de lungime len
*/
int V[DIM], T[DIM], D[DIM];
int n, m, i, p, u, mid;
/**
D[i] = indicele din V al celei mai mici valori in care se poate
termina un sir de lungime i (de fapt D[i] = poZitia din V a unei
astfel de valori) folosind elementele deja parcurse
m = lungimea maxima LIS gasita pana acum
p, u = capete in cautarea binara (p - st, u - dr)
**/
ifstream cin("scmax.in");
ofstream cout("scmax.out");
void sol(int i) {
if (i) {
sol(T[i]);
cout<<V[i]<<" ";
}
}
int main() {
cin>>n;
for (i=1;i<=n;i++)
cin>>V[i];
m = 1;
D[1] = 1;
// parcurgem elementul curent v[i], vrem sa ii gasim lungimea la care poate fi plasat
// cautam prima pozitie p in 1..m pentru care v[d[p]] >= v[i]
// asta inseamna pentru toate lungimile < p, capatul este < v[i], deci putem extinde
// la p, capatul este >= v[i], deci v[i] poate "ibunatati" capatul (devine mai mic)
// exact aceasta este bs clasic pe vectorul de capete
for (i=2;i<=n;i++) {
p = 1; ///caut pozitia ultimei valori D[poz] din
/// D pentru care V[i] > V[ D[poz] ]
u = m;
while (p<=u) {
mid = p+(u-p)/2;
// d[mid] este un indice din v, deci capatul pentru lungimea mid este v[d[mid]]
if (V[ D[mid] ] >= V[i])
// cautam mai in stanga, vrem prima pozitie cu >=
u = mid - 1;
else
// capatul este < v[i], deci putem extinde cel putin pana aici
p = mid + 1;
}
/**
dupa:
p: prima pozitie unde v[d[p]] >= v[i] (sau p = m + 1 daca nu exista)
u: ultima pozitie unde v[d[u]] < v[i]
obs: u = p - 1
lungimea maxima pe care o putem extinde cu v[i] este u
**/
if (p > m) {
// inseamna ca v[i] este mai mare decat toate capetele curente, deci
// putem extinde LIS ul maxim: crestem m, noul capat pentru lungime m devine i
m++;
D[m] = i;
// parintele lui i este capatul optim al subsirului de lungime m-1
T[i] = D[p-1];
} else {
D[p] = i;
T[i] = D[p-1];/// extind sirul terminat pe pozitia p-1(u)
}
}
cout<<m<<"\n";
sol(D[m]); ///in T este un vector de tati pentru indici din V
return 0;
}