Cod sursa(job #670155)

Utilizator laurionLaurentiu Ion laurion Data 28 ianuarie 2012 15:53:50
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.57 kb
//scmax cu upper_bound by Laur Ion
//Complexitate: O(N lg K)  | unde K e lungimea scmax  (cautarea binara este facuta pe Q (nu v) a carui lungime este mereu <= K => O(lg K) complexitate)
#include<cstdio>
#include<iostream>
#include<fstream>
#include<vector>
#include<cstring>
#include<string>
#include<sstream>
#include<iterator>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#include<cassert>

#define filein  "scmax.in"
#define fileout "scmax.out"

using namespace std;

ifstream fin(filein);
ofstream fout(fileout);

int n;
//vector<int> G[100000+10];
#define NMax 100005

int v[NMax], prev[NMax];
vector<int> Q; //vector de pozitii ale scmax

bool cmp(int val, int poz)
{
    return val < v[poz];
}
inline void afis(int poz)
{
    if(poz == 0) {
        return;
    }
    afis(prev[poz]);
    fout<<v[poz]<<' ';
}
inline int bin_search (int val)
{
    int st=-1,dr=Q.size()-1,m;
    while(dr-st>1) 
    {
        m = ((unsigned int)st + (unsigned int)dr) >> 1;
        if(v[Q[m]] < val)
            st=m;
        else
            dr=m;
    }
//    if (dr == Q.size() || A[dr] != x) 	// cand ultimul element din sir e mai mic decat x, st = A.length - 1 si dr = A.length
//        return -1; 						// sau cand dr este undeva in interiorul sirului,  A[st] < x < A[dr]
//    else 								//x e in sir
        return dr;
}
int main()
{
    fin>>n;
    for(int i=1; i<=n; ++i)
        fin>>v[i];

    Q.push_back(1);
//    memset(prev,0xff,sizeof(prev));
    for(int i=2; i<=n; ++i) {
        if (v[i] > v[Q.back()]) {   //daca elementul curent e mai mare decat ultimul element a scmax curente (v[Q.back])
            prev[i] = Q.back();     //se adauga la capatul lui Q si se continua
            Q.push_back(i);
            continue;
        }
        //cauta cel mai mic element referentiat de Q care e mai mare decat v[i]
        int p = bin_search(v[i]);
        assert(p>=0);
//        
//		if (v[i] < v[Q[p]]) 
//        {
//			if (p > 0) 
//                prev[i] = Q[p-1];
//			Q[p] = i;
//		}
        vector<int>::iterator it = upper_bound(Q.begin(), Q.end(), v[i], cmp); //
        if(it != Q.begin() && v[*(it-1)] == v[i]) //upper_bound face <= cumva deci trebuie sa verificam si sa nu fie elemente egale
            continue;
        int _pit=it-Q.begin();
        if(v[i]<v[*it]) {
            if(it != Q.begin())
                prev[i] = *(it-1);
            *it = i;
        }
    }

    fout<<Q.size()<<'\n';

    afis(Q.back());
    fout<<'\n';

    fout.close();
    return 0;
}