Cod sursa(job #2965418)

Utilizator matei.tudoseMatei Tudose matei.tudose Data 15 ianuarie 2023 11:47:35
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.52 kb
#include <fstream>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;

ifstream fin("scmax.in");
ofstream fout("scmax.out");

struct elem
{
    // Lungimea maxima a secventei si pozitia pe interval in care gasim acest maxim (din sirul initial)
    int lungMax, nod;
} BIT[100005];

stack<int> ansStack;
int n, numbers[100005], indexes[100005], tata_de[100005];

int getLSB(int x)
{
    return (x & (-x));
}

void setValue(int x, int poz)
{
    // Daca avem un maxim mai bun, salvam pozitia din care l-am obtinut
    int cPoz = poz;
    for (; cPoz <= n; cPoz += getLSB(cPoz))
    {
        if (BIT[cPoz].lungMax < x)
        {
            BIT[cPoz].lungMax = x;
            BIT[cPoz].nod = poz;
        }
    }
}

elem getValue(int poz)
{
    // Numerele din care vin posibilele raspunsuri trebuie sa fie < ca numarul din care dam
    int pivot = poz + 1;
    elem ans = {0, 0};
    for (; poz > 0; poz -= getLSB(poz))
    {
        if (ans.lungMax < BIT[poz].lungMax && numbers[pivot] != numbers[BIT[poz].nod])
            ans = BIT[poz];
    }
    return ans;
}

bool compareIndexes(int x, int y)
{
    if (numbers[x] == numbers[y])
        return x < y;
    return numbers[x] < numbers[y];
}

int main()
{
    fin >> n;
    for (int i = 1; i <= n; i++)
    {
        fin >> numbers[i];
        indexes[i] = i;
        // Eliminam duplicatele consecutive
        if (i > 1 && numbers[i] == numbers[i - 1])
            i--, n--;
    }
    // Sortam index-urile in functie de numerele initiale
    sort(indexes + 1, indexes + 1 + n, compareIndexes);
    // Ne bazam pe ideea ca doar numerele dinainte de index[i] (1...index[i]-1) sunt cele care au
    // aparut in trecut si cerem lungimea maxima pe acelea, nu putem cere pe cele din viitor
    for (int i = 1; i <= n; i++)
    {
        if (i == 1)
        {
            setValue(1, indexes[i]);
            continue;
        }
        elem ans = getValue(indexes[i] - 1);
        // Pentru reconstructia unei variante de raspuns:
        tata_de[indexes[i]] = ans.nod;
        setValue(ans.lungMax + 1, indexes[i]);
    }
    // Pivotul in functie de care comparam este maxim posibil
    numbers[n + 1] = INT32_MAX;
    elem ans = getValue(n);
    fout << ans.lungMax << "\n";
    int header = ans.nod;
    // Ne ducem din tata in tata pentru a obtine drumul
    while (header)
    {
        ansStack.push(numbers[header]);
        header = tata_de[header];
    }
    while (!ansStack.empty())
    {
        fout << ansStack.top() << " ";
        ansStack.pop();
    }
    fout << "\n";
    return 0;
}