Cod sursa(job #1692518)

Utilizator stoianmihailStoian Mihail stoianmihail Data 21 aprilie 2016 00:19:48
Problema Hotel Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.45 kb
#include <stdio.h>
#include <set>

using std::set;

#define aibSize 131072
#define Nadejde 100000

int N, M;
char sign[Nadejde + 2];
int aib[aibSize + 1];

set <int> sl;
set <int>::iterator it;

/** Adauga in multime elementul "x". **/
inline void add(int x, int val) {
  if (x == 0) {
    return;
  }

  do {
    aib[x] += val;
    x += x & -x;
  } while (x <= aibSize);
}

/** Da-mi maximul din multime. **/
inline int bSearch(int val) {
  int x = 0, interval = aibSize >> 1;

  while (interval) {
    if (aib[x + interval] < val) {
      val -= aib[x += interval];
    }
    interval >>= 1;
  }
  return x + 1;
}

/** Initializeaza datele. **/
inline void init() {
  int i;

  add(N, +1);
  for (i = 1; i <= N; i++) {
    sign[i] = '0';
  }
}

/** Idee preluata de la smenul lui Mars (marcheaza cu + sau -). **/
inline void push(int pos, char c) {
  sl.insert(pos);
  sign[pos] = c;
}

inline void pop(int pos) {
  sl.erase(pos);
  sign[pos] = '0';
}

/** Da-mi cea mai din dreapta pozitie cu obstacol <= "pos". **/
inline int left(int pos) {
  it = sl.lower_bound(pos);
  if (it == sl.begin()) {
    return 1;
  } else {
    it--;
    return *it;
  }
}

/** Da-mi cea mai din stanga pozitie cu obstacol >= pos. **/
inline int right(int pos) {
  it = sl.lower_bound(pos);
  if (it == sl.end()) {
    return N + 1;
  } else {
    return *it;
  }
}

int main(void) {
  int i, a, b, task, lo, hi;
  FILE *f = fopen("hotel.in", "r");
  freopen("hotel.out", "w", stdout);

  fscanf(f, "%d %d", &N, &M);
  init();

  /* Raspunde la intrebari. */
  for (i = 1; i <= M; i++) {
    fscanf(f, "%d", &task);
    if (task == 1) {
      fscanf(f, "%d %d", &a, &b);
      b += a - 1;

      /* Adauga secventa [a, b]. */
      if (sl.empty()) {
        lo = 1;
        hi = N + 1;
      } else {
        it = sl.upper_bound(a);
        if (it == sl.begin()) {
          lo = 1;
          hi = *it;
        } else if (it == sl.end()) {
          it--;
          lo = *it;
          hi = N + 1;
        } else {
          hi = *it;
          it--;
          lo = *it;
        }
      }

      add(hi - lo, -1);
      add(a - lo, +1);
      add(hi - b - 1, +1);

      if (sign[a] == '-') {
        pop(a);
      } else {
        push(a, '+');
      }
      if (sign[b + 1] == '+') {
        pop(b + 1);
      } else {
        push(b + 1, '-');
      }
    } else if (task == 2) {
      fscanf(f, "%d %d", &a, &b);
      b += a - 1;

      /* Stergem o secventa inclusa intr-un sir de "1". */
      if (sign[a] != '+' && sign[b + 1] != '-') {
        push(a, '-');
        push(b + 1, '+');

        add(b - a + 1, +1);
      /* Stergem prefixul unui sir de "1". */
      } else if (sign[a] == '+' && sign[b + 1] != '-') {
        pop(a);
        push(b + 1, '+');

        lo = left(a);
        add(a - lo, -1);
        add(b - lo + 1, +1);
      /* Stergem sufixul unui sir de "1". */
      } else if (sign[a] != '+' && sign[b + 1] == '-') {
        push(a, '-');
        pop(b + 1);

        hi = right(b + 1);
        add(hi - b - 1, -1);
        add(hi - a, +1);
      /* Stergem un sir de "1". */
      } else {
        pop(a);
        pop(b + 1);

        lo = left(a);
        hi = right(b + 1);
        add(hi - b - 1, -1);
        add(a - lo, -1);
        add(hi - lo, +1);
      }
    } else {
      if (aib[aibSize]) {
        fprintf(stdout, "%d\n", bSearch(aib[aibSize]));
      } else {
        fprintf(stdout, "0\n");
      }
    }
  }
  fclose(f);
  fclose(stdout);

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