Cod sursa(job #1865744)

Utilizator TimoteiCopaciu Timotei Timotei Data 2 februarie 2017 00:35:19
Problema Subsir crescator maximal Scor 90
Compilator cpp Status done
Runda Arhiva educationala Marime 3.05 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#define nMax 100001

using namespace std;
int n, order[nMax], lMax, last[nMax], bestIndex;
typedef struct{
 int number, poz;
} element;
typedef struct{
   int bestL, index;
} nod;
typedef struct {
   bool operator() (const element &x, const element &y) const{
     return (x.number < y.number);
   }
}comp;
vector <element> v;
vector <int> best_subString;
element y;
nod arb[4 * nMax + 66];

void read()
{
    ifstream fin("scmax.in");
    fin >> n;
    int x;
    for(int i = 1; i <= n; ++i){
     fin >> x;
     y.number = x;
     y.poz = i;
      v.push_back(y);
    }
}
void normalize()
{
    sort(v.begin(), v.end(), comp());
    int same = 0;
    order[v[0].poz] = 1;
    for(int i = 1; i < n; ++i){
        if(v[i].number == v[i - 1].number) same++;
        order[v[i].poz] = i + 1 - same;
        }

    for(int i = 1; i < v.size(); ++i)
        if(v[i].number == v[i - 1].number)
            v.erase(v.begin() + i), i--; //sterg elementele care se repeta in v
}
void update(int node, int st, int dr, int a, int b)
{
   if(st == dr){
    arb[node].bestL = b;
    arb[node].index = a;
   }
    else{
        int mij = (st + dr) / 2;
        if(a <= mij) update(2 * node, st, mij, a, b);
         else update(2 * node + 1, mij + 1, dr, a, b);
       if(arb[node].bestL <= max(arb[2 * node].bestL, arb[2 * node + 1].bestL)){
        if(arb[2 * node].bestL == arb[2 * node + 1].bestL)
             arb[node].index = a;
           else
             if(arb[2 * node].bestL > arb[2 * node + 1].bestL)
                 arb[node] = arb[2 * node];
              else arb[node] = arb[2 * node + 1];
       }
    }
}
void query(int node, int st, int dr, int a, int b)
{
  if(a <= st && dr <= b){
    if(arb[node].bestL >= lMax){
        lMax = arb[node].bestL;
        bestIndex = arb[node].index;
    }
  }
  else{
    int mij = (st + dr) / 2;
    if(a <= st) query(2 * node, st, mij, a, b);
    if(b > mij) query(2 * node + 1, mij + 1, dr, a, b);
  }
}
void find_the_substring()
{
    int next = arb[1].index;
    for(int i = 1; i <= arb[1].bestL; ++i){
        best_subString.push_back(v[next - 1].number);
        next = last[next];
    }
}
void solve()
{
   for(int i = 1; i <= n; ++i){
    lMax = 0;
    if(order[i] > 1)
        query(1, 1, v.size(), 1, order[i] - 1);   // aflu lungimea maxima lMax a unui subsir care se termina pe unul din elementele mai mici decat cel curent

    lMax++;
    update(1, 1, v.size(), order[i], lMax); // actualizez lungimea maxima a subsirului care se termina cu elementul curent
    last[order[i]] = bestIndex; // pe elementul curent l-am adaugat la subsirul terminat cu elementul bestIndex
    }

   find_the_substring();
}
void write()
{
    ofstream fout("scmax.out");
    fout << arb[1].bestL << '\n';
    for(int i = best_subString.size() - 1; i >= 0; --i)
        fout << best_subString[i] << ' ';
}
int main()
{
    read();
    normalize();
    solve();
    write();
    return 0;
}