Cod sursa(job #532941)

Utilizator Bit_MasterAlexandru-Iancu Caragicu Bit_Master Data 12 februarie 2011 19:22:47
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.19 kb
/*
	x[i] -> pozitia in vectorul v pe care se termina un subsir de lungime i.
            dintre toate pozitiile posibile, este stocata cea in care v[i] minim.
            pentru numerele de pana acum.

	Pentru fiecare pozitie din vectorul v (1,2,...,n)
se gaseste cel mai mare l (lungimea maxima de subsir la care poate fi
atasat)
astfel incat v[x[j]] (valoarea elementului la care atasez) sa fie mai
mica decat v[i] (valoarea elementului curent)

noii valori i se marcheaza pozitia in x la lungimea maxima posibila.

in nx se retine lungimea maxima obtinuta

chiar daca un numar nu mareste lungimea subsirurilor, poate micsora valoarea
de pe o anumita lungime (facilitand formarea viitoarelor subsiruri; chiar
daca noua valoare ar putea sa se lege crescator de urmatoarele, nu se poate
deoarece apare pe o pozitie mai mare decat acestea si deci nu mai formeaza
subsir)
dar valorile din v indicate din x sunt in ordine crescatoare, din moment ce
prin imbunatatirea valorii de pe o lungime, aceasta ramane mai mica decat
valorile de pe urmatoarele pozitii.
noua valoare pusa pentru o lungime va fi sigur mai mica decat cea existenta,
pentru ca altfel ar fi fost pusa legata de aceasta, pe o pozitie mai mare.


pred[i] -> elementul precedent din subsirul ales pentru elementul v[i]

pred[i] = x[j]

*/

#include <cstdio>

const int N = 100001;
int v[N],n;
int x[N],nx=0;
int pred[N];

inline int max (int a, int b)
{
	return (a>b)?a:b;
}

void citire()
{
	scanf("%i",&n);
	for (int i = 1; i <= n; ++i)
		scanf("%i",&v[i]);
}

int lung_max(int i)//lungimea maxima de subsir in care sfarsitul indicat de x este mai mic decat noua valoare v[i].
{
	int l = 0;
	for (int pas = 1<<17; pas > 0; pas /= 2)
		if ((l+pas <= nx)&&(v[x[l+pas]] < v[i]))
			l += pas;
	return l;
}

void calculare_x()
{
	int l;
	for (int i = 1; i <= n; ++i)
	{
		l = lung_max(i);
		x[l+1] = i;
		nx = max (nx,l+1);
		pred[i] = x[l];
	}
}

void afisare(int poz)
{
	if (pred[poz] != 0)
		afisare(pred[poz]);
	printf("%i ",v[poz]);
}

int main()
{
	freopen("scmax.in","r",stdin);
	freopen("scmax.out","w",stdout);
	citire();
	calculare_x();
	printf("%i\n",nx);
	afisare(x[nx]);
	return 0;
}