Cod sursa(job #1558257)

Utilizator stoianmihailStoian Mihail stoianmihail Data 28 decembrie 2015 22:11:56
Problema Order Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 4.25 kb
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_VALUE 2000000001
#define Nadejde 700000
#define R 524287
#define MAX_LEVEL 20

/**  Implementare K-th element!
 *  Ne vom folosi de structura Skip-Lists.
 *  Pe langa zona de memorie, vom retine si un vector "d", cu
 * urmatoarea semnificatie:
 *  "Vectorul "d" reprezinta distanta pana la urmatorul element
 * din nivel."
 *
 *  Pentru mai multe informatii:
 *
    http://drum.lib.umd.edu/bitstream/
   handle/1903/544/CS-TR-2286.1.pdf;jsessionid=4F143B4B585765118DC
   2CD0217A2AF21?sequence=2
 *
 *  Multumim Doamne!
**/

int N, K;
int level;             // nivelul maxim al fiecatui element.
int bufPtr;            // primul slot nealocat.
int d[Nadejde];        // distanta pana la urmatorul element din nivel.
int sl[Nadejde];       // zona de memorie prealocata.
int space[MAX_LEVEL];  // folosit in timpul selectiei.
int update[MAX_LEVEL]; // folosit in timpul inserarii.

/** Initializeaza structura. **/
void init() {
  sl[0] = -MAX_VALUE;
  sl[MAX_LEVEL + 1] = MAX_VALUE;

  int l;
  for (l = 0; l < MAX_LEVEL; l++) {
    sl[l + 1] = MAX_LEVEL + 1;
    d[l + 1] = 1;
  }
  bufPtr = MAX_LEVEL + 2;
  level = 1;
}

/** Da-mi un nivel random. **/
int randomLevel() {
  int l = 1, r;
  for (r = rand() & R; r & 1; r >>= 1) {
    l++;
  }
  return l;
}

/** Insereaza valoarea "x" in lista de nivel "0". **/
void lowLevel(int x) {
  sl[bufPtr] = x;
  d[bufPtr + 1] = 1;
  sl[bufPtr + 1] = sl[update[0] + 1];
  sl[update[0] + 1] = bufPtr;
}

/** Insereaza valoarea "x" in structura. **/
void insert(int x) {
  int l, save, pos = 0;

  /* Cauta pointerii ce trebuie actualizati. */
  for (l = level - 1; l >= 0; l--) {
    space[l] = 0;
    while (sl[sl[pos + l + 1]] < x) {
      space[l] += d[pos + l + 1];
      pos = sl[pos + l + 1];
    }
    update[l] = pos;
  }
  for (l = level; l < MAX_LEVEL; l++) {
    update[l] = space[l] = 0;
  }

  int newLevel = randomLevel();
  if (newLevel > level) {
    level = newLevel;
  }

  /* Introdu-l pe "x" in structura, restabilind pointerii si distantele. */
  lowLevel(x);
  for (l = 1; l < newLevel; l++) {
    save = space[l - 1] + d[update[l - 1] + l];
    d[bufPtr + l + 1] = d[update[l] + l + 1] - save + 1;
    d[update[l] + l + 1] = save;

    sl[bufPtr + l + 1] = sl[update[l] + l + 1];
    sl[update[l] + l + 1] = bufPtr;
  }
  for (l = newLevel; l < MAX_LEVEL; l++) {
    d[update[l] + l + 1]++;
  }
  bufPtr += newLevel + 1;
}

/** Sterge valoarea "x" din structura. **/
void erase(int x) {
  int l, pos = 0;
  for (l = level - 1; l >= 0; l--) {
    while (sl[sl[pos + l + 1]] < x) {
      pos = sl[pos + l + 1];
    }
    update[l] = pos;
  }
  for (l = level; l < MAX_LEVEL; l++) {
    update[l] = 0;
  }
  pos = sl[pos + 1];

  l = 0;
  while ((l < level) && (sl[update[l] + l + 1] == pos)) {
    d[update[l] + l + 1] += d[pos + l + 1] - 1;
    sl[update[l] + l + 1] = sl[pos + l + 1];
    l++;
  }
  while (l < MAX_LEVEL) {
    d[update[l] + l + 1]--;
    l++;
  }
}

/** Sterge elementul de pe pozitia "k". **/
void erasebyGrade(int k, FILE *f) {
  int l, pos = 0, grade = 0;
  for (l = level - 1; l >= 0; l--) {
    while (grade + d[pos + l + 1] <= k) {
      grade += d[pos + l + 1];
      pos = sl[pos + l + 1];
    }
    update[l] = pos;
  }
  for (l = level; l < MAX_LEVEL; l++) {
    update[l] = 0;
  }
  fprintf(f, "%d ", sl[pos]);

  l = 0;
  while ((l < level) && (sl[update[l] + l + 1] == pos)) {
    d[update[l] + l + 1] += d[pos + l + 1] - 1;
    sl[update[l] + l + 1] = sl[pos + l + 1];
    l++;
  }
  while (l < MAX_LEVEL) {
    d[update[l] + l + 1]--;
    l++;
  }
}

/** Da-mi elementul de pe pozitia "k". **/
int listSelect(int k) {
  int l, pos = 0, grade = 0;
  for (l = level - 1; l >= 0; l--) {
    while (grade + d[pos + l + 1] <= k) {
      grade += d[pos + l + 1];
      pos = sl[pos + l + 1];
    }
  }
  return sl[pos];
}

int main(void) {
  int i, x, last = 2;
  FILE *in = fopen("order.in", "r");
  FILE *out = fopen("order.out", "w");

  init();
  srand(time(NULL));

  /* Citeste intrebarile. */
  fscanf(in, "%d", &N);
  for (i = 1; i <= N; i++) {
    insert(i);
  }
  fclose(in);

  for (i = 0; i < N; i++) {
    x = (last + i) % (N - i);
    x = !x ? N - i : x;
    last = x;
    erasebyGrade(x, out);
  }
  fclose(out);

  /// Multumim Doamne!
  puts("Doamne ajuta!");
  return 0;
}