Cod sursa(job #2226363)

Utilizator inquisitorAnders inquisitor Data 30 iulie 2018 03:19:51
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.08 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

FILE *f = fopen("rmq.in", "r");

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];
int shl[MAX_LOG + 1] = {1, 2, 4, 8, 16, 32, 64, 128, 256};

#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];

#define IN_BUFFER_SIZE 0xBBAEE0

char inBuffer[IN_BUFFER_SIZE];

__attribute__((always_inline)) unsigned int get_number()
{
    static unsigned int p = 0x0; unsigned int number = 0x0;

    for(inBuffer[p] > 0x2F || ++p; inBuffer[p] > 0x2F; ++p)

        number = number * 0xA + inBuffer[p] - 0x30;

    return number;
}

char outBuffer[0x7A1]; ///WTF??

unsigned int p = ~0x0;

__attribute__((always_inline)) void put_number(unsigned int x)
{
    unsigned int digits =  x > 0x1869F ? 0x7 :
                           x > 0x270F  ? 0x6 :
                           x > 0x3E7   ? 0x5 :
                           x > 0x63    ? 0x4 :
                           x > 0x9     ? 0x3 : 0x2;

    for(unsigned int i = digits; --i; x /= 0xA)
    {
        outBuffer[p + i] = x % 0xA + 0x30;
    }

    outBuffer[p = p + digits] = 0xA;
}

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 - shl[lg[b - a + 1]] + 1]);
  } else {
    return INF;
  }
}

int main(void) {

    freopen("rmq.in", "r", stdin);

    fread(inBuffer, 0x1, IN_BUFFER_SIZE, stdin);

  int i, a, b, pass = 0;
  N = get_number();
  M = get_number();
  int sq = sqrt(N);

  lg[1] = 0;
  for (i = 0; i < N; i++) {
    val[i] = get_number();
    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 - shl[j - 1];
    for (i = 0; i < tmp; i++) {
      rmq[j][i] = MIN(rmq[j - 1][i], rmq[j - 1][i + shl[j - 1]]);
    }
  }

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

  freopen("rmq.out", "w", stdout);

  fwrite(outBuffer, 1, p, stdout);

  return 0;
}