Cod sursa(job #2240497)

Utilizator gabrielxCojocaru Gabriel-Codrin gabrielx Data 13 septembrie 2018 17:01:31
Problema Subsir crescator maximal Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.15 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;
    vector<int> ans;
};

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;
    nodes[node].ans.clear();
    
    if (st < dr) {
        int mij = (st + dr) / 2;
        initSegmentTree(node * 2, st, mij);
        initSegmentTree(node * 2 + 1, mij + 1, dr);
    }
}

void updateSegmetTree(int node, int pos, vector<int> &val) {
    if (nodes[node].st == nodes[node].dr) {
        nodes[node].ans = val;
        return;
    }
    
    int mij = (nodes[node].st + nodes[node].dr) / 2;
    if (pos <= mij) {
        updateSegmetTree(node * 2, pos, val);
    } else {
        updateSegmetTree(node * 2 + 1, pos, val);
    }
    
    int sizeSubarbSt = nodes[node * 2].ans.size(), sizeSubarbDr = nodes[node * 2 + 1].ans.size();
    if (sizeSubarbSt == sizeSubarbDr) {
        if (nodes[node * 2].ans[sizeSubarbSt - 1] > nodes[node * 2 + 1].ans[sizeSubarbDr - 1]) {
            nodes[node].ans = nodes[node * 2 + 1].ans;
        } else {
            nodes[node].ans = nodes[node * 2].ans;
        }
    } else if (sizeSubarbSt > sizeSubarbDr) {
        nodes[node].ans = nodes[node * 2].ans;
    } else {
        nodes[node].ans = nodes[node * 2  + 1].ans;
    }
}

vector<int> querySegmentTree(int node, int st, int dr) {
    if (dr == 0) {
        vector<int> emptyVec;
        return emptyVec;
    }
    
    if (nodes[node].st >= st && nodes[node].dr <= dr) {
        return nodes[node].ans;
    }
    
    int mij = (nodes[node].st + nodes[node].dr) / 2;
    
    vector<int> subarbStVec, subarbDrVec;
    if (st <= mij) {
        subarbStVec = querySegmentTree(node * 2, st, dr);
    }
    
    if (dr > mij) {
        subarbDrVec = querySegmentTree(node * 2 + 1, st, dr);
    }
    
    int sizeSubarbSt = subarbStVec.size(), sizeSubarbDr = subarbDrVec.size();
    if (sizeSubarbSt == sizeSubarbDr) {
        if (sizeSubarbSt == 0) {
            return subarbStVec;   
        }
        
        if (subarbStVec[sizeSubarbSt - 1] > subarbDrVec[sizeSubarbDr - 1]) {
            return subarbDrVec;
        } else {
            return subarbStVec;
        }
    } else if (sizeSubarbSt > sizeSubarbDr) {
        return subarbStVec;
    } else {
        return subarbDrVec;
    }
}

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) {
	    vector<int> queryVec = querySegmentTree(1, 1, a[i].second - 1);
	    queryVec.push_back(a[i].first);
	    updateSegmetTree(1, a[i].second, queryVec);
	}
	
	cout << nodes[1].ans.size() << '\n';
	for (int i = 0; i < nodes[1].ans.size(); ++i) {
	    cout << nodes[1].ans[i] << ' ';
	}
	
	return 0;
}