Cod sursa(job #2240553)

Utilizator gabrielxCojocaru Gabriel-Codrin gabrielx Data 13 septembrie 2018 18:32:39
Problema Subsir crescator maximal Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.39 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define MAX_N 100005
#define MAX_NODES 265000

using namespace std;

ifstream cin("scmax.in");
ofstream cout("scmax.out");


struct Node {
	int st;
	int dr;
	int posOfBestList;
};

bool mycompare(pair<int, int> &lhs, pair<int, int> &rhs) {
	if (lhs.first == rhs.first) {
		return lhs.second > rhs.second;
	}

	return lhs.first < rhs.first;
}

int N;
vector<pair<int, int>> a(MAX_N);
vector<vector<int>> lists(MAX_N);
vector<Node> nodes(MAX_NODES);

void initSegmentTree(int node, int st, int dr) {
	nodes[node].st = st;
	nodes[node].dr = dr;

	if (st < dr) {
		int mij = (st + dr) / 2;
		initSegmentTree(node * 2, st, mij);
		initSegmentTree(node * 2 + 1, mij + 1, dr);
		nodes[node].posOfBestList = nodes[node * 2 + 1].posOfBestList;
	}
	else {
		nodes[node].posOfBestList = st;
	}
}

void updateSegmetTree(int node, int pos) {
	if (nodes[node].st == nodes[node].dr) {
		return;
	}

	int mij = (nodes[node].st + nodes[node].dr) / 2;
	if (pos <= mij) {
		updateSegmetTree(node * 2, pos);
	}
	else {
		updateSegmetTree(node * 2 + 1, pos);
	}

	int sizeSubarbSt = lists[nodes[node * 2].posOfBestList].size(), sizeSubarbDr = lists[nodes[node * 2 + 1].posOfBestList].size();
	if (sizeSubarbSt == sizeSubarbDr) {
		if (lists[nodes[node * 2].posOfBestList][sizeSubarbSt - 1] > lists[nodes[node * 2 + 1].posOfBestList][sizeSubarbDr - 1]) {
			nodes[node].posOfBestList = nodes[node * 2 + 1].posOfBestList;
		}
		else {
			nodes[node].posOfBestList = nodes[node * 2].posOfBestList;
		}
	}
	else if (sizeSubarbSt > sizeSubarbDr) {
		nodes[node].posOfBestList = nodes[node * 2].posOfBestList;
	}
	else {
		nodes[node].posOfBestList = nodes[node * 2 + 1].posOfBestList;
	}
}

int querySegmentTree(int node, int st, int dr) {
	if (dr == 0) return 0;

	if (nodes[node].st >= st && nodes[node].dr <= dr) {
		return nodes[node].posOfBestList;
	}

	int mij = (nodes[node].st + nodes[node].dr) / 2;

	int posOfBestListInSubarbSt = 0, posOfBestListInSubarbDr = 0;
	if (st <= mij) {
		posOfBestListInSubarbSt = querySegmentTree(node * 2, st, dr);
	}

	if (dr > mij) {
		posOfBestListInSubarbDr = querySegmentTree(node * 2 + 1, st, dr);
	}

	int sizeSubarbSt = lists[posOfBestListInSubarbSt].size(), sizeSubarbDr = lists[posOfBestListInSubarbDr].size();
	if (sizeSubarbSt == sizeSubarbDr) {
		if (sizeSubarbSt == 0) {
			return posOfBestListInSubarbSt;
		}

		if (lists[posOfBestListInSubarbSt][sizeSubarbSt - 1] > lists[posOfBestListInSubarbDr][sizeSubarbDr - 1]) {
			return posOfBestListInSubarbDr;
		}
		else {
			return posOfBestListInSubarbSt;
		}
	}
	else if (sizeSubarbSt > sizeSubarbDr) {
		return posOfBestListInSubarbSt;
	}
	else {
		return posOfBestListInSubarbDr;
	}
}

int main() {
	cin >> N;

	for (int i = 1; i <= N; ++i) {
		cin >> a[i].first;
		a[i].second = i;
	}

	sort(a.begin() + 1, a.begin() + 1 + N, mycompare);
	initSegmentTree(1, 1, N);

	for (int i = 1; i <= N; ++i) {
		int bestListInInterval = querySegmentTree(1, 1, a[i].second - 1);
		lists[a[i].second] = lists[bestListInInterval];
		lists[a[i].second].push_back(a[i].first);

		updateSegmetTree(1, a[i].second);
	}

	cout << lists[nodes[1].posOfBestList].size() << '\n';
	for (int i = 0; i < lists[nodes[1].posOfBestList].size(); ++i) {
		cout << lists[nodes[1].posOfBestList][i] << ' ';
	}

	return 0;
}