Cod sursa(job #1445651)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 30 mai 2015 17:32:16
Problema Subsir crescator maximal Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.65 kb
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <stack>
#define _submit
#ifdef _submit
#define InFile "scmax.in"
#define OutFile "scmax.out"
#else
#define InFile "fis.in"
#define OutFile "fis.out"
#endif

//#define _smalltest
#ifdef _smalltest
#define MAXN 5
#define MAXARB 10
#else
#define MAXN 100010
#define MAXARB 300030
#endif

int sequence[MAXN];
int sortedSeq[MAXN];
int prev[MAXN];
std::pair<int,int> arbInt[MAXARB];
int arbSz;

int gudSz(int N) {
	int p = 1;
	while (p < N)
		p <<= 1;
	return p;
}

void vidareArb() {
	for (int i = arbSz; i < (arbSz << 1); i++)
		arbInt[i] = { 0, i - arbSz + 1 };
	for (int i = arbSz - 1; i>0; i--)
		arbInt[i] = std::max(arbInt[i << 1], arbInt[(i << 1) + 1]);
}

void update(int pos, int x) {
	pos += arbSz - 1;
	arbInt[pos].first = x;
	pos >>= 1;
	while (pos) {
		std::pair<int,int> aux = std::max(arbInt[pos << 1], arbInt[(pos << 1) + 1]);
		if (aux.first == arbInt[pos].first)
			break;
		arbInt[pos] = aux;
		pos >>= 1;
	}
}

std::pair<int,int> query(int left, int right) {
	left += arbSz - 1;
	right += arbSz - 1;
	std::pair<int, int> r = { 0, 0 };
	while (left <= right) {
		r = std::max(r, std::max(arbInt[left], arbInt[right]));
		left = (left + 1) << 1;
		right = (right - 1) << 1;
	}
	return r;
}

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OutFile, "w", stdout));
	int N;
	scanf("%d", &N);
	arbSz = gudSz(N);
	vidareArb();
	for (int i = 1; i <= N; i++) {
		scanf("%d", &sequence[i]);
		sortedSeq[i] = sequence[i];
	}
	std::sort(sortedSeq + 1, sortedSeq + N + 1);
	for (int i = 1; i <= N; i++) {
		int left = 1;
		int right = N;
		int pos = -1;
		int bound = -1;
		while (left <= right) {
			int mid = (left + right) >> 1;
			if (sortedSeq[mid] == sequence[i]) {
				if (arbInt[mid + arbSz - 1].first == 0) {
					pos = mid;
					right = mid - 1;
				}
				else
					left = mid + 1;
			}
			else if (sequence[i] <= sortedSeq[mid])
				right = mid - 1;
			else {
				left = mid + 1;
				bound = mid;
			}
		}
		assert(pos != -1);
		if (bound == -1) {
			update(pos, 1);
			prev[pos] = 0;
		}
		else {
			std::pair<int, int> bestmax = query(1, bound);
			update(pos, bestmax.first + 1);
			prev[pos] = bestmax.second;
		}
	}
	std::pair<int, int> maxlen = { 0, 0};
	for (int i = arbSz; i < arbSz + N; i++) {
		if (arbInt[i] > maxlen)
			maxlen = arbInt[i];
	}
	printf("%d\n", maxlen.first);
	std::stack<int> S;
	int curNod = maxlen.second;
	while (curNod) {
		S.push(curNod);
		curNod = prev[curNod];
	}
	while (!S.empty()) {
		printf("%d ", sortedSeq[S.top()]);
		S.pop();
	}
	return 0;
}