Pagini recente » Cod sursa (job #1213566) | Cod sursa (job #963345) | Cod sursa (job #540047) | Cod sursa (job #525055) | Cod sursa (job #1254736)
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctype.h>
#include <cstring>
#include <string>
#include <ctime>
#include <cassert>
#include <utility>
using namespace std;
#define LIM 100005
int dp[LIM], A[4 * LIM + 10], maxim, pos, val, inceput, sfarsit;
// idee ce utilizeaza DP + Arb de Intervale
// ideea acestui program este ca se calculeaza cu
// programare dinamica: lungimea celui mai lung subsir care se termina in i si care respecta ca e strict crescator
// doar ca acum se priveste inapoi si atunci tranzitiile sunt:
// dp[i] = max(dp[j] | j < i && dp[i] > dp[j]) + 1;
// pentru a calcula acel maxim in timp mai mic de o(n) putem sa o facem utilizand arborii de intervale
void updateARB(int nod, int st, int dr) {
if(st == dr) { // am ajuns la o frunza - am ajuns pe pozitia care vreau sa updatez
A[nod] = val;
return;
}
int m = (st + dr) / 2;
if(pos <= m)
updateARB(2 * nod, st, m);
else
updateARB(2 * nod + 1, m + 1, dr);
A[nod] = max(A[2 * nod], A[2 * nod + 1]);
}
void queryARB(int nod, int st, int dr) {
if(inceput <= st && dr <= sfarsit) {
if(maxim < A[nod])
maxim = A[nod];
return;
}
int m = (st + dr) / 2;
if(m >= inceput)
queryARB(2 * nod, st, m);
if(m < sfarsit)
queryARB(2 * nod + 1, m + 1, dr);
}
pair<long long, int> vp[LIM];
pair<int, long long> rez[LIM];
long long x;
int main() {
freopen("scmax.in", "r", stdin);
freopen("scmax.out","w", stdout);
int n, a[LIM];
cin >> n;
// ================ citire si normalizare ===============
for(int i = 1; i <= n; i++) {
cin >> x;
vp[i - 1] = make_pair(x, i);
}
sort(vp, vp + n);
int t = 1;
a[vp[0].second] = t;
rez[a[vp[0].second]] = make_pair(t, vp[0].first);
for(int i = 1; i < n; i++) {
if(vp[i].first != vp[i - 1].first) {
t++;
}
a[vp[i].second] = t;
rez[a[vp[i].second]] = make_pair(t, vp[i].first);
}
// ================ initializare dp =====================
for(int i = 1; i <= n; i++) {
dp[i] = 1;
}
// ================ rezolvarea cerintei conform comentariilor de la inceputul programului ================
inceput = 1;
sfarsit = n;
// dp[i] = "lungimea celui mai lung subsir care se termina in i"
for(int i = 1; i <= n; i++) {
maxim = -1;
sfarsit = a[i] - 1;
if(sfarsit > 0) {
queryARB(1, 1, n);
dp[i] = max(dp[i], maxim + 1);
}
pos = a[i];
val = dp[i];
sfarsit = n;
updateARB(1, 1, n);
}
// problema cere lg celui mai lung subsir (nu neaparat cel care se termina in n) -> caut maximul dintre toate cele n calculate
int mx = -1, pos = -1;
for(int i = 1; i <= n; i++) {
if(mx < dp[i]) {
mx = dp[i];
pos = i;
}
}
// ================== afisarea rezultatelor ===============
cout << mx << "\n";
vector<long long> v;
for(int i = pos; i > 0 && mx > 0; i--) {
if(dp[i] == mx) {
v.push_back(rez[a[i]].second);
mx--;
}
}
reverse(v.begin(), v.end());
int sz = v.size();
for(int i = 0; i < sz - 1; i++) {
cout << v[i] << " ";
}
if(sz - 1 >= 0)
cout << v[sz - 1] << "\n";
return 0;
}