Cod sursa(job #1454173)

Utilizator GilgodRobert B Gilgod Data 25 iunie 2015 16:43:55
Problema Subsir crescator maximal Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 2.21 kb
#include <iostream>
#include <fstream>
#include <assert.h>

inline int left_child(int k) { return k * 2; }
inline int right_child(int k) { return k * 2 + 1; }
inline int max(int a, int b) { ((a) > (b)) ? (a) : (b); }

const char IN[] = "scmax.in", OUT[] = "scmax.out";
const int NMAX = 100001;

using namespace std;

int V[NMAX];
int N;
//arbor de intervale:
//pe frunze o sa fie best(i) pentru i de la 1 la N
//folosit ca sa determine best(1,j) cu j < i la PD
int T[NMAX * 4];
int PRE[NMAX * 4];
int PI[NMAX];
int maxim;
int pred;

void update(int node, int low, int high, int pos, int val) {
	if (low == high) {
		T[node] = val;
		PRE[node] = pos;
		return;
	}
	int m = low + (high - low) / 2;
	if (pos <= m) update(left_child(node), low, m, pos, val);
	else update(right_child(node), m + 1, high, pos, val);
	if (T[left_child(node)] > T[right_child(node)]) {
		T[node] = T[left_child(node)];
		PRE[node] = PRE[left_child(node)];
	}
	else {
		T[node] =  T[right_child(node)];
		PRE[node] = PRE[right_child(node)];
	}
}

void query(int node, int low, int high, int a, int b, int cand) {
	if (a <= low && high <= b && V[PRE[node]] < cand) {
		if (maxim < T[node]) {
			maxim = T[node];
			pred = PRE[node];
		}
		return;
	}
	int m = low + (high - low) / 2;
	if (a <= m) query(left_child(node), low, m, a, b, cand);
	if (b > m) query(right_child(node), m + 1, high, a, b, cand);
}

inline void read_data() {
	assert(freopen(IN, "r", stdin));
	assert(scanf("%d", &N));
	for (int i = 1; i <= N; ++i) {
		assert(scanf("%d", &V[i]));
		//C.B.: best(i) = 1 pentru 1..N
		update(1, 1, N, i, 1);
	}
	fclose(stdin);
}

void print_result(int pred) {
	if (pred == 0) return;
	print_result(PI[pred]);
	printf("%d ", V[pred]);
}

inline void PD() {
	for (int i = 2; i <= N; ++i) {
		maxim = -1;
		pred = 0;
		query(1, 1, N, 1, i - 1, V[i]);
		if (maxim != -1) {
			update(1, 1, N, i, maxim + 1);
			PI[i] = pred;
		}
		else {
			update(1, 1, N, i, 1);
			PI[i] = 0;
		}
	}
	maxim = -1;
	pred = 0;
	query(1, 1, N, 1, N, 0x3f3f3f3f);
	printf("%d\n", maxim);
	print_result(pred);
}

int main() {
	read_data();
	assert(freopen(OUT, "w", stdout));
	PD();
	fclose(stdout);
	return 0;
}