Pagini recente » Cod sursa (job #1916762) | Cod sursa (job #845157) | Cod sursa (job #3247986) | Cod sursa (job #3192115) | Cod sursa (job #2961108)
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
using namespace std;
// ifstream cin("input");ofstream cout("output");
ifstream cin("scmax.in");ofstream cout("scmax.out");
// SOLUTIE O(N logN)
const int inf = 2e9 + 1;
int n;
vector<int> numere;
vector<int> dp;
// dp[i] = pozitia din vector (numere) a celei mai mici valori de pana acum
// care se afla la finalul unui subsir strict crescator de lungime i
vector<int> inainte; // inainte[i] = care este pozitia numarului care vine inaintea mea (folosesc la afisare)
int MAX; // raspunsul = lungimea maxima
void citire() {
cin >> n;
numere.resize(n+2);
dp.resize(n+2);
inainte.resize(n+2);
for (int i = 1; i <= n; i++) {
cin >> numere[i];
dp[i] = n + 1; // initializez cu pozitia n+1 care reprezinta infinitul
}
numere[n + 1] = inf; // ii dau valoarea de infinit
}
int cautBin(int i) {
int st = 0, dr = i - 1;
int ans = 0;
while (st <= dr) {
int mij = st + dr;
mij /= 2;
if (numere[i] > numere[dp[mij]]) {
ans = mij;
st = mij + 1;
}
else {
dr = mij - 1;
}
}
return ans;
}
void rezolvare() {
for (int i = 1; i <= n; i++) {
int ans = cautBin(i); // caut lungimea maxima la care pot sa ma lipesc
if (numere[i] < numere[dp[ans + 1]]) { // actualizez dinamica doar daca eu sunt mai mic
dp[ans + 1] = i; // eu devin capatul subsirului de lungima ans + 1
}
inainte[i] = dp[ans]; // actualizez pozitia inaintea mea (vin din dp[ans])
MAX = max(MAX, ans + 1); // actualizez lungimea celui mai lung subsir crescator
}
}
void afisare() {
cout << MAX << '\n';
vector < int > raspuns;
int now = dp[MAX];
while (now) {
raspuns.push_back(numere[now]);
now = inainte[now];
}
reverse(raspuns.begin(), raspuns.end());
for (auto& x : raspuns) {
cout << x << " ";
}
cout << '\n';
}
int main(){
citire();
rezolvare();
afisare();
}