Pagini recente » Cod sursa (job #53920) | Cod sursa (job #2724926) | Cod sursa (job #2199619) | Cod sursa (job #2442561) | Cod sursa (job #2965418)
#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;
}