Cod sursa(job #1489468)

Utilizator stoianmihailStoian Mihail stoianmihail Data 21 septembrie 2015 10:35:05
Problema Hashuri Scor 70
Compilator c Status done
Runda Arhiva educationala Marime 3.21 kb
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <ctype.h>

#define INFINITY 2000000001
#define Nadejde 3000000
#define Dragoste 4096
#define MAX_LEVEL 20
#define Randomize -524289

int level;             // nivelul maxim din structura.
int bufPtr;            // primul slot nealocat.
int sl[Nadejde];       // zona de memorie prealocata.
int pos = Dragoste;    // pozitia in "buff".
int update[MAX_LEVEL]; // folosit in timpul inserarii.
char c, buff[Dragoste];

/** Ia urmatorul caracter din "f". **/
char getChar(FILE *f) {
  if (pos == Dragoste) {
    fread(buff, 1, Dragoste, f);
    pos = 0;
  }
  return buff[pos++];
}

/** Citeste urmatorul numar din "f". **/
void freef(FILE *f, const char *arg, int *result) {
  *result = 0;
  do {
    c = getChar(f);
  } while (!isdigit(c));
  do {
    *result = (*result << 3) + (*result << 1) + c - '0';
    c = getChar(f);
  } while (isdigit(c));
}

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

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

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

/** Introdu valoarea "x". **/
void insert(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;
  }

  /* Nu permitem duplicate. */
  if (sl[sl[pos + 1]] != x) {
    int newLevel = randomLevel();
    if (newLevel > level) {
      for (l = level; l < newLevel; l++) {
        update[l] = 0;
      }
      level = newLevel;
    }

    sl[bufPtr] = x;
    for (l = 0; l < newLevel; l++) {
      sl[bufPtr + l + 1] = sl[update[l] + l + 1];
      sl[update[l] + l + 1] = bufPtr;
    }
    bufPtr += newLevel + 1;
    assert(bufPtr < Nadejde);
  }
}

/** Cauta elementul "x". **/
int search(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];
    }
  }
  return (sl[sl[pos + 1]] == x);
}

/** Sterge elementul "x". **/
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;
  }
  pos = sl[pos + 1];

  /* Refacem acei pointeri care pointeaza la "pos"(restul trec deasupra noastra). */
  if (sl[pos] == x) {
    l = 0;
    while ((l < MAX_LEVEL) && (sl[update[l] + l + 1] == pos)) {
      sl[update[l] + l + 1] = sl[pos + l + 1];
      l++;
    }
  }
}

int main(void) {
  int N, task, val;
  FILE *in = fopen("hashuri.in", "r");
  FILE *out = fopen("hashuri.out", "w");

  init();

  freef(in, "%d", &N);
  while (N--) {
    freef(in, "%d", &task);
    freef(in, "%d", &val);
    if (task == 1) {
      insert(val);
    } else {
      if (task == 2) {
        erase(val);
      } else {
        fprintf(out, "%d\n", search(val));
      }
    }
  }
  fclose(in);
  fclose(out);

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