Cod sursa(job #1940379)

Utilizator stoianmihailStoian Mihail stoianmihail Data 26 martie 2017 16:21:18
Problema Range minimum query Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.71 kb
#include <stdio.h>
#include <ctype.h>
#include <math.h>

const int INF = 1e9;
#define MAX_N 100000
#define MAX_SQ 317
#define MAX_LOG 8

int N, M;
int val[MAX_N + 1];
int lg[MAX_N + 3];
int left[MAX_N + 2];
int right[MAX_N + 2];
int rmq[MAX_LOG + 1][MAX_SQ + 1];

#define MAX_OUT 7000000
#define MAX_BUFF 65536 * 2
int ptr = MAX_BUFF;
char c, buff[MAX_BUFF];
int result, now;
char out[MAX_OUT];
int ss, dig[MAX_LOG];

inline char getChar(FILE *f) {
  if (ptr == MAX_BUFF) {
    fread(buff, 1, MAX_BUFF, f);
    ptr = 0;
  }
  return buff[ptr++];
}

inline int freef(FILE *f) {
  result = 0;
  do {
    c = getChar(f);
  } while (!isdigit(c));
  do {
    result = (result << 3) + (result << 1) + c - '0';
    c = getChar(f);
  } while (isdigit(c));
  return result;
}

void put(int x) {
  if (x == 0) {
    dig[ss++] = 0;
  }
  while (x) {
    result = x / 10;
    dig[ss++] = x - (result << 3) - (result << 1);
    x = result;
  }

  while (ss) {
    out[now++] = dig[ss - 1] + '0';
    ss--;
  }
  out[now++] = '\n';
}

inline int MIN(const int X, const int Y) {
  return X < Y ? X : Y;
}

inline int naive(int a, int b) {
  int ret = INF;
  while (a <= b) {
    if (val[a] < ret) {
      ret = val[a];
    }
    a++;
  }
  return ret;
}

inline int look(const int a, const int b) {
  if (a <= b) {
    return MIN(rmq[lg[b - a + 1]][a], rmq[lg[b - a + 1]][b - (1 << lg[b - a + 1])]);
  } else {
    return INF;
  }
}

int main(void) {
  int i, a, b, pass = 0;
  FILE *f = fopen("rmq.in", "r");
  N = freef(f);
  M = freef(f);
  int sq = sqrt(N);

  lg[1] = 0;
  for (i = 0; i < N; i++) {
    val[i] = freef(f);
    if (i == pass) {
      left[i] = val[i];
      pass += sq;
    } else {
      left[i] = MIN(val[i], left[i - 1]);
    }
    lg[i + 2] = lg[(i + 2) >> 1] + 1;
  }

  pass = sq * ((N - 1) / sq);
  right[N] = INF;
  for (i = N - 1; i >= 0; i--) {
    if (i == pass - 1) {
      right[i] = val[i];
      pass -= sq;
    } else {
      right[i] = MIN(right[i + 1], val[i]);
    }
    if (i == pass) {
      rmq[0][pass / sq] = right[i];
    }
  }

  int j, tmp, size = (N - 1) / sq + 1;
  for (j = 1; j <= lg[size]; j++) {
    tmp = size - (1 << (j - 1));
    for (i = 0; i < tmp; i++) {
      rmq[j][i] = MIN(rmq[j - 1][i], rmq[j - 1][i + (1 << (j - 1))]);
    }
  }

  while (M) {
    a = freef(f) - 1;
    b = freef(f) - 1;
    tmp = a / sq;
    pass = b / sq;
    if (tmp == pass) {
      put(naive(a, b));
    } else {
      put(MIN(left[b], MIN(right[a], look(tmp + 1, pass - 1))));
    }
    M--;
  }
  fclose(f);

  freopen("rmq.out", "w", stdout);
  fwrite(out, 1, now, stdout);
  fclose(stdout);
  return 0;
}