Cod sursa(job #1527322)

Utilizator stoianmihailStoian Mihail stoianmihail Data 17 noiembrie 2015 23:28:18
Problema Zeap Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.18 kb
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

#define INFINITY 1000000001
#define R 524287
#define Nadejde 5000000
#define MAX_LEVEL 20
#define Smerenie 3

typedef struct {
  int inside, level, bufPtr;
  int MIN_VAL, MAX_VAL;
  int list[Nadejde];
} sl;

sl set, map;
char s[Smerenie];      // operatia curenta.
int update[MAX_LEVEL]; // folosit in timpul cautarii.

/** abs(X). **/
int ABS(int X) {
  return X > 0 ? X : -X;
}

/** Initializeaza structura "skip". **/
void init(sl *skip, int min, int max) {
  skip -> MIN_VAL = min;
  skip -> MAX_VAL = max;
  skip -> list[0] = skip -> MIN_VAL;
  skip -> list[MAX_LEVEL + 1] = skip -> MAX_VAL;

  int i;
  for (i = 1; i <= MAX_LEVEL; i++) {
    skip -> list[i] = MAX_LEVEL + 1;
  }
  skip -> bufPtr = MAX_LEVEL + 2;
  skip -> 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 structura "skip", cu restrictia "task". **/
void insert(sl *skip, int x, int task) {
  int l, pos = update[0];

  int curr = skip -> list[pos + 1];
  if ((task) || (skip -> list[curr] != x)) {
    int newLevel = randomLevel();
    if (newLevel > skip -> level) {
      for (l = skip -> level; l < newLevel; l++) {
        update[l] = 0;
      }
      skip -> level = newLevel;
    }
    skip -> list[skip -> bufPtr] = x;
    for (l = 0; l < newLevel; l++) {
      skip -> list[skip -> bufPtr + l + 1] = skip -> list[update[l] + l + 1];
      skip -> list[update[l] + l + 1] = skip -> bufPtr;
    }
    skip -> bufPtr += newLevel + 1;
    assert(skip -> bufPtr < Nadejde);
    skip -> inside++;
  }
}

/** Sterge din structura "skip" valoarea "x". **/
void erase(sl *skip, int x) {
  int l, pos = update[0];
  /* Refacem acei pointeri care pointeaza la "curr" (restul trec deasupra noastra). */
  int curr = skip -> list[pos + 1];
  if (skip -> list[curr] == x) {
    l = 0;
    while ((l < skip -> level) && (skip -> list[update[l] + l + 1] == curr)) {
      skip -> list[update[l] + l + 1] = skip -> list[curr + l + 1];
      l++;
    }
    skip -> inside--;
  }
}

/** Cauta in structura "skip" valoarea "x". **/
void search(sl *skip, int x) {
  int l, pos = 0;
  for (l = skip -> level; l >= 0; l--) {
    while (skip -> list[skip -> list[pos + l + 1]] < x) {
      pos = skip -> list[pos + l + 1];
    }
    update[l] = pos;
  }
}

int main(void) {
  srand(time(NULL));
  int x, pos, curr, next;
  FILE *in = fopen("zeap.in", "r");
  FILE *out = fopen("zeap.out", "w");

  init(&set, -INFINITY, INFINITY);
  init(&map, 0, (INFINITY << 1) + 1);

  insert(&map, INFINITY << 1, 0);
  map.inside--;

  /* Cat timp mai avem instructiuni de efectuat. */
  while (fscanf(in, "%s", s) != EOF) {
    switch (s[0]) {
      /* Inserare. */
      case 'I':
        /* Citirea datelor. */
        fscanf(in, "%d", &x);

        /* Pregatirea pozitiilor. */
        search(&set, x);
        pos = update[0];
        assert(pos + 1 < Nadejde);
        next = set.list[pos + 1];
        assert(next < Nadejde);

        /* Conditiile structurii. */
        if (set.list[next] != x) {
          /* Insereaza in "set" valoarea "x". */
          insert(&set, x, 0);

          /* Sterge din "map" valoarea |sl[pos] - sl[next]|. */
          search(&map, ABS(set.list[pos] - set.list[next]));
          erase(&map, ABS(set.list[pos] - set.list[next]));

          /* Insereaza in "map" valoarea |x - sl[pos]|. */
          search(&map, ABS(x - set.list[pos]));
          insert(&map, ABS(x - set.list[pos]), 1);

          /* Insereaza in "map" valoarea |x - sl[next]|. */
          search(&map, ABS(x - set.list[next]));
          insert(&map, ABS(x - set.list[next]), 1);
        }
        break;
      /* Stergere. */
      case 'S':
        /* Citirea datelor. */
        fscanf(in, "%d", &x);

        /* Pregatirea pozitiilor. */
        search(&set, x);
        pos = update[0];
        assert(pos + 1 < Nadejde);
        curr = set.list[pos + 1];
        assert(curr + 1 < Nadejde);
        next = set.list[curr + 1];

        /* Daca se afla in structura. */
        if (set.list[curr] == x) {
          /* Sterge din "set" valoarea "x". */
          erase(&set, x);

          assert(next < Nadejde);

          /* Sterge din "map" valoarea |sl[pos] - sl[curr]|. */
          search(&map, ABS(set.list[pos] - set.list[curr]));
          erase(&map, ABS(set.list[pos] - set.list[curr]));

          /* Sterge din "map" valoarea |sl[curr] - sl[next]|. */
          search(&map, ABS(set.list[curr] - set.list[next]));
          erase(&map, ABS(set.list[curr] - set.list[next]));

          /* Insereaza in structura "map" valoarea |sl[pos] - sl[next]|. */
          search(&map, ABS(set.list[pos] - set.list[next]));
          insert(&map, ABS(set.list[pos] - set.list[next]), 1);
        } else {
          fprintf(out, "%d\n", -1);
        }
        break;
      /* Cautare. */
      case 'C':
        /* Citirea datelor. */
        fscanf(in, "%d", &x);

        /* Pregatirea pozitiilor. */
        search(&set, x);
        pos = update[0];

        /* Afisarea solutiei. */
        assert(pos + 1 < Nadejde && set.list[pos + 1] < Nadejde);
        fprintf(out, "%d\n", (set.list[set.list[pos + 1]] == x));
        break;
      case 'M':
        switch (s[1]) {
          /* Diferenta in modul minima. */
          case 'I':
            /* Afisarea solutiei. */
            assert(map.list[1] < Nadejde);
            fprintf(out, "%d\n", set.inside > 1 ? map.list[map.list[1]] : -1);
            break;
          /* Diferenta in modul maxima. */
          case 'A':
            /* Afisarea solutiei. */
            if (set.inside > 1) {
              search(&set, set.MAX_VAL);
              assert(update[0] < Nadejde);
              fprintf(out, "%d\n", set.list[update[0]] - set.list[set.list[1]]);
            } else {
              fprintf(out, "-1\n");
            }
            break;
        }
        break;
    }
  }
  fclose(in);
  fclose(out);

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