Cod sursa(job #822299)

Utilizator ciorile.chioareBogatu Adrian ciorile.chioare Data 23 noiembrie 2012 10:40:43
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.6 kb
#include <cstdio>


FILE* in;
FILE* out;

template<class T>
int binary_search(T* v, int *index, int a, int b, const T& value) {
  if(a == b) {
    return (!(v[index[a]] < value))?(a):(a + 1);
  }
  int mid = (a + b) / 2;
  if(v[index[mid]] < value) {
    return binary_search(v, index, mid + 1, b, value);
  }
  else {
    return binary_search(v, index, a, mid, value);
  }
}

void afis(int *v, int s, int n, const char mess[]) {
    fprintf(stderr, "%s", mess);
    for(int i = s; i < n + s; ++i)
      fprintf(stderr, "%d ", v[i]);
    fprintf(stderr, "\n");
}

/*
 *  Functia care determina un subsir crescator maximal dintr-un vector
 */
int* scmax(int *v, int &n) {

  int j;

  /* Alocarea memoriei */

  /* best[i] = lungimea subsirului crescator maximal ce se termina pe poz i */
  int *best = new int[n + 1];
  /* m[i] = indicele celui mai mic numar din v care are lungimea i */
  int *m = new int[n + 1];
  /* vector de predecesori */
  int *prev = new int[n + 1];

  /* jmax este pozitia din v unde se termina cel mai lung subsir crescator */
  int jmax = 0;

  /* initializam vectorii ajutatori */
  best[1] = 1;
  v[0] = 0;
  /* imax e lungimea lui m completat pana la un anumit pas */
  int imax = 0;

  for(int i = 1; i <= n; ++i) {
    /* cautam intervalul minim in care se afla v[i] O(log(n))*/
    j = binary_search(v, m, 0, imax, v[i]);
    /* introducem lungimea scm ce se termina pe pozitia i in best[i]*/
    best[i] = j;
    /* memoram lungimea maxima dintre lungimile subsirurilor crescatoare */
    if(best[i] > best[jmax])
      jmax = i;
    /* retinem elementul anterior unui element dintr-un subsir crescator */
    prev[i] = m[j - 1];
    /* punem indicele minimului in pozitia j (stim v[i] < v[m[j]])*/
    m[j] = i;
    /* retinem lungimea lui m (pentru cautarea binara) */
    if(j > imax)
      imax++;
  }
  fprintf(out, "%d\n", imax);
  /* generam rezultatul ajutandu-ne de vectorul de predecesori */
  int *rez = new int[imax + 1];
  j = 0;
  rez[j++] = jmax;
  for(int i = jmax; prev[i]; i = prev[i]) {
    rez[j] = prev[i];
    j++;
  }

  /* Afisare */
  for(int i = j - 1; i >= 0; --i)
    fprintf(out, "%d ", v[rez[i]]);
  fprintf(out, "\n");

  /* Dezalocare */
  delete best;
  delete m;
  delete prev;
  delete rez;
}

int main(int argc, char **argv) {

  argc--;
  argv++;

  //in = fopen(argv[0], "r");
  //out = fopen(argv[1], "w");
  in = fopen("scmax.in", "r");
  out = fopen("scmax.out", "w");

  int n;

  fscanf(in, "%d", &n);

  int *price = new int[n + 1];
  for(int i = 1; i <= n; ++i) {
    fscanf(in, "%d", price + i);
  }

  scmax(price, n);

  delete price;

  fclose(in);
  fclose(out);
  return 0;
}