Pagini recente » Cod sursa (job #1983697) | Cod sursa (job #1461379) | Cod sursa (job #503234) | Cod sursa (job #2316948) | Cod sursa (job #3344051)
// SPDX-License-Identifier: BSD-3-Clause
#include <algorithm>
#include <fstream> // ifstream, ofstream
#include <iostream> // cin, cout, cerr
#include <memory> // unique_ptr pentru Task
#include <vector> // vector
using namespace std;
class Task {
public:
void solve() {
read_input();
write_output(get_result());
}
private:
int n;
vector<int> v;
vector<int> scmax_vec; // vectorul cu numerele din scmax
void read_input() {
ifstream fin("scmax.in");
fin >> n;
v.resize(n + 1);
for (int i = 1; i <= n; ++i) {
fin >> v[i];
}
fin.close();
}
int get_result() {
// v = vectorul dat
// sol = lungimea SCMAX
// pos = pozitia pe care se termina SCMAX gasit pentru problema data
// solutia se termina cu v[pos]
// inainte in solutie apare v[prec[pos]]
// v [prec[prec[pos]]]
// si tot asa... in sir avem sol elemente!
// Din cauza ca stim unde se termina solutia, o vom putea reconstrui in ordine inversa
// (de la sfarsit catre inceput). Putem stoca rezultatul intr-un vector si sa il inversam la final.
vector<int> dp(n + 1); // in explicatii indexarea incepe de la 1
vector<int> prec(n + 1); // dp[1], ..., dp[n] | prec[1], ..., prec[n]
// caz de baza
dp[1] = 1; // [ v[1] ] este singurul subsir (crescator) care se termina pe 1
prec[1] = 0; // nu are precedent
// caz general
for (int i = 2; i <= n; ++i) {
dp[i] = 1; // [ v[i] ] - este un subsir (crescator) care se termina pe i
prec[i] = 0; // nu are precedent (cel putin momentan)
// incerc sa il pun pe v[i] la finalul tuturor solutiilor disponibile
// o solutie se termina cu un element v[j]
for (int j = 1; j < i; ++j) {
// solutia triviala: v[i]
if (v[j] < v[i]) {
// din (..., v[j]) pot obtine (..., v[j], v[i])
// (caz in care prec[i] = j)
// voi alege j-ul curent, cand alegerea imi gaseste o solutie mai buna decat ce am deja
if (dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
prec[i] = j;
}
}
}
}
// solutia e maximul din vectorul dp
int sol = dp[1], pos = 1;
for (int i = 2; i <= n; ++i) {
if (dp[i] > sol) {
sol = dp[i];
pos = i;
}
}
// reconstruim SCMAX: v[pos] este ultimul element, inainte v[prec[pos]], etc.
scmax_vec.clear();
for (int i = 0; i < sol; ++i) {
// v[pos] este ultimul element pe care il stiu din SCMAX
scmax_vec.push_back(v[pos]);
// inainte de el era v[prec[pos]] (..., v[ prec[pos] ], v[ pos ])
pos = prec[pos];
}
reverse(scmax_vec.begin(), scmax_vec.end()); // oglindire vector solutie
return sol;
}
void write_output(int result) {
ofstream fout("scmax.out");
// afiseaza solutia
fout << result << "\n";
for (size_t i = 0; i < scmax_vec.size(); ++i) {
fout << (i ? " " : "") << scmax_vec[i];
}
fout << "\n";
fout.close();
}
};
// [ATENTIE] NU modifica functia main!
int main() {
std::unique_ptr<Task> task {new (nothrow) Task()};
if (!task) {
std::cerr << "new failed: WTF are you doing? Throw your PC!\n";
return -1;
}
task->solve();
return 0;
}