Cod sursa(job #219072)

Utilizator tvladTataranu Vlad tvlad Data 5 noiembrie 2008 01:30:16
Problema Subsir crescator maximal Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.42 kb
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;

const int N = 100000;
const int AINT_SIZE = 1 << 18;

int n, na;
int a[N], v[N];
map<int, int> norm;
int top_length;
pair<int, int> ai[AINT_SIZE];
int d[N], prev[N];
pair<int, int> pair_zero(0,-1);

void update ( int node, int node_start, int node_length, int target, int value, int poz ) {
	if (node_length > 1) {
		if (target < node_start + (node_length >> 1))
			update(node*2+1, node_start, node_length >> 1, target, value, poz); else
			update(node*2+2, node_start + (node_length >> 1), node_length >> 1, target, value, poz);
		if (ai[node*2+1].first > ai[node*2+2].first) {
			ai[node].first = ai[node*2+1].first;
			ai[node].second = ai[node*2+1].second;
		} else {
			ai[node].first = ai[node*2+2].first;
			ai[node].second = ai[node*2+2].second;
		}
	} else {
		ai[node].first = value;
		ai[node].second = poz;
	}
}

pair<int, int> &query ( int node, int node_start, int node_length, int target_start, int target_end ) {
	if (target_start == node_start && target_end == node_start + node_length - 1)
		return ai[node];
	int mid = node_start + (node_length >> 1);
	pair<int, int> &r1 = (target_start < mid) ? query(node*2+1, node_start, node_length >> 1, target_start, min(target_end, mid-1)) : pair_zero;
	pair<int, int> &r2 = (target_end >= mid) ? query(node*2+2, mid, node_length >> 1, max(target_start, mid), target_end) : pair_zero;
	return (r1 > r2) ? r1 : r2;
}

int main() {
	freopen("scmax.in","rt",stdin);
	freopen("scmax.out","wt",stdout);
	scanf("%d",&n);
	for (top_length = 1; top_length < n; top_length <<= 1);
	for (int i = 0; i < n; ++i) {
		scanf("%d",&a[i]);
		v[i] = a[i];
	}
	
	sort(a,a+n);
	na = 1;
	for (int i = 1; i < n; ++i)
		if (a[i-1] != a[i])
			a[na++] = a[i];
	for (int i = 0; i < na; ++i) norm[a[i]] = i;
	for (int i = 0; i < n; ++i) v[i] = norm[v[i]];

	for (int i = 0; i < AINT_SIZE; ++i) ai[i].second = -1;

	int max = 0, pm = 0;
	for (int i = 0; i < n; ++i) {
		pair<int, int> &qu = query(0,0,top_length,0,v[i]-1);
		d[i] = qu.first + 1;
		prev[i] = qu.second;
		update(0, 0, top_length, v[i], d[i], i);
		if (d[i] > max) {
			max = d[i];
			pm = i;
		}
	}

	printf("%d\n",max);
	vector<int> rev;
	for (int i = pm; i >= 0; i = prev[i])
		rev.push_back(a[v[i]]);
	for (int i = rev.size()-1; i >= 0; --i)
		printf("%d ",rev[i]);
	printf("\n");
	return 0;
}