Cod sursa(job #2240601)

Utilizator gabrielxCojocaru Gabriel-Codrin gabrielx Data 13 septembrie 2018 19:39:21
Problema Subsir crescator maximal Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.43 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 lis;
	int currentPos;
	int prevPos;
	int lastVal;
};

struct QueryAnswer {
	int prevPos;
	int lis;
	int lastVal;
	int currentPos;
	int currentVal;

	QueryAnswer(int prevPos, int lis, int lastVal, int currentPos) {
		this->prevPos = prevPos;
		this->lis = lis;
		this->lastVal = lastVal;
		this->currentPos = currentPos;
	}
};

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<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].currentPos = nodes[node * 2].currentPos;
	}
	else {
		nodes[node].currentPos = st;
	}
}

void updateSegmetTree(int node, int pos, QueryAnswer *queryAns) {
	if (nodes[node].st == nodes[node].dr) {
		nodes[node].lastVal = queryAns->currentVal;
		nodes[node].lis = queryAns->lis + 1;
		nodes[node].prevPos = queryAns->currentPos;

		return;
	}

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

	Node leftNode = nodes[node * 2], rightNode = nodes[node * 2 + 1];
	if (leftNode.lis == rightNode.lis) {
		if (leftNode.lastVal > rightNode.lastVal) {
			nodes[node].currentPos = rightNode.currentPos;
			nodes[node].lastVal = rightNode.lastVal;
			nodes[node].lis = rightNode.lis;
			nodes[node].prevPos = rightNode.prevPos;
		}
		else {
			nodes[node].currentPos = leftNode.currentPos;
			nodes[node].lastVal = leftNode.lastVal;
			nodes[node].lis = leftNode.lis;
			nodes[node].prevPos = leftNode.prevPos;
		}
	} else if (leftNode.lis > rightNode.lis) {
		nodes[node].currentPos = leftNode.currentPos;
		nodes[node].lastVal = leftNode.lastVal;
		nodes[node].lis = leftNode.lis;
		nodes[node].prevPos = leftNode.prevPos;
	} else {
		nodes[node].currentPos = rightNode.currentPos;
		nodes[node].lastVal = rightNode.lastVal;
		nodes[node].lis = rightNode.lis;
		nodes[node].prevPos = rightNode.prevPos;
	}
}

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

	if (nodes[node].st >= st && nodes[node].dr <= dr) {
		return new QueryAnswer(nodes[node].prevPos, nodes[node].lis, nodes[node].lastVal, nodes[node].currentPos);
	}

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

	QueryAnswer *leftSubarbQueryAnswer = new QueryAnswer(0, 0, 0, 0), *rightSubarbQueryAnswer = new QueryAnswer(0, 0, 0, 0);
	if (st <= mij) {
		leftSubarbQueryAnswer = querySegmentTree(node * 2, st, dr);
	}

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

	if (leftSubarbQueryAnswer->lis == rightSubarbQueryAnswer->lis) {
		if (leftSubarbQueryAnswer->lastVal > rightSubarbQueryAnswer->lastVal) {
			return rightSubarbQueryAnswer;
		} else {
			return leftSubarbQueryAnswer;
		}
	} else if (leftSubarbQueryAnswer->lis > rightSubarbQueryAnswer->lis) {
		return leftSubarbQueryAnswer;
	} else {
		return rightSubarbQueryAnswer;
	}
}

int main() {
	cin.sync_with_stdio(false);
	cout.sync_with_stdio(false);

	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) {
		QueryAnswer *queryAns = querySegmentTree(1, 1, a[i].second - 1);
		queryAns->currentVal = a[i].first;
		updateSegmetTree(1, a[i].second, queryAns);

		free(queryAns);
	}

	int currentInterval = nodes[1].currentPos;
	vector<int> sol;

	QueryAnswer *queryAns, *prevQueryAns = new QueryAnswer(0, 0, 0, 0);
	do {
		free(prevQueryAns);
		queryAns = querySegmentTree(1, currentInterval, currentInterval);
		sol.push_back(queryAns->lastVal);
		currentInterval = queryAns->prevPos;
		prevQueryAns = queryAns;
	} while (queryAns->lis > 1);

	cout << sol.size() << '\n';
	for (int i = sol.size() - 1; i >= 0; --i) {
		cout << sol[i] << ' ';
	}

	return 0;
}