Cod sursa(job #3317739)

Utilizator 0021592Grecu rares 0021592 Data 25 octombrie 2025 10:36:06
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.76 kb
#include <fstream>
#include <algorithm>
const int NMAX = 1e5+5;
using namespace std;
ifstream in("scmax.in");
ofstream out("scmax.out");
int n, res[NMAX], v[NMAX], lst[NMAX], dp[NMAX], aib[NMAX], best, up[NMAX];
void update(int x, int ind)
{
    for (; x <= n; x += (x&(-x)))
        if (dp[ind] > dp[aib[x]])
            aib[x] = ind; ///daca noul dp este mai mare, atunci e mai smecher noul dp decat cel vechi si il bagam in aib
}
int query(int x)
{
    int mx = 0;
    for (; x>0; x -= (x&(-x)))
        if (dp[aib[x]] > dp[mx])
            mx = aib[x]; ///daca cumva mx-ul querried este mai mic decat termenul ales, luam termenul ales
    return mx;
}
int main()
{
    in >> n;
    for (int i = 1; i <= n; i++)
    {
        in >> v[i];
        res[i] = lst[i] = v[i];
    }
    sort(lst+1, lst+1+n);
    int lst_lg = 1;
    for (int i = 2; i <= n; i++)
        if (lst[i] != lst[lst_lg])
            lst[++lst_lg] = lst[i]; ///ne creem o lista de termeni distinci din sirul n;
    for (int i = 1; i <= n; i++)
        v[i] = lower_bound(lst+1, lst+lst_lg+1, v[i])-lst; ///pentru fiecare v[i] ii gasim pozitia in lst for any reason
    for (int i = 1; i <= n; i++)
    {
        up[i] = query(v[i]-1); ///cautam pe v[i]-1 why? aaa ca sa nu il luam pe v[i] insasi.
        dp[i] = dp[up[i]]+1; ///up[i] reprezinta termenul precedent
        update(v[i], i); ///tocmai ne-am updatat dp-ul, deci updatatam aib-ul
    }
    for (int i = 1; i <= n; i++)
        if (dp[best] < dp[i])
            best = i;
    out << dp[best] << '\n'; ///best reprezinta ultimul termen
    lst_lg = 0;
    for (int i = best; i; i = up[i])
        lst[++lst_lg] = res[i]; ///creem vectorul rezultat
    for (int i = lst_lg; i > 0; i--)
        out << lst[i] << ' ';
}