Cod sursa(job #2226279)

Utilizator inquisitorAnders inquisitor Data 30 iulie 2018 01:21:50
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.72 kb
#include <fstream>
#include <string.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];
int shl[MAX_LOG + 1] = {1, 2, 4, 8, 16, 32, 64, 128, 256};

class Reader
{
public:
    Reader() {}
    Reader(const char *file_name)
    {
        input_file = fopen(file_name, "r");
        cursor = 0;
        fread(buffer, SIZE, 1, input_file);
    }
    inline Reader &operator >>(int &n)
    {
        while(buffer[cursor] < '0' || buffer[cursor] > '9')
        {
            advance();
        }
        n = 0;
        while('0' <= buffer[cursor] && buffer[cursor] <= '9')
        {
            n = n * 10 + buffer[cursor] - '0';
            advance();
        }
        return *this;
    }
private:
    FILE *input_file;
    static const int SIZE = 1 << 17;
    int cursor;
    char buffer[SIZE];
    inline void advance()
    {
        ++ cursor;
        if(cursor == SIZE)
        {
            cursor = 0;
            fread(buffer, SIZE, 1, input_file);
        }
    }
};

class Writer
{
public:
    Writer(const char *name):
        m_stream(name)
    {
        memset(m_buffer, 0, sizeof(m_buffer));
        m_pos = 0;
    }

    Writer& operator<<(int a)
    {
        int many = 0;
        do
        {
            digit_buffer[many++] = a % 10 + '0';
            a /= 10;
        }
        while (a > 0);
        for (int i = many - 1; i >= 0; --i)
            putchar(digit_buffer[i]);
        return *this;
    }

    Writer& operator<<(const char *s)
    {
        for (; *s; ++s)
            putchar(*s);
        return *this;
    }

    ~Writer()
    {
        m_stream.write(m_buffer, m_pos);
    }

private:
    void putchar(char c)
    {
        m_buffer[m_pos++] = c;
        if (m_pos == kBufferSize)
        {
            m_stream.write(m_buffer, m_pos);
            m_pos = 0;
        }
    }

    static const int kBufferSize = 1 << 17;
    std::ofstream m_stream;
    char m_buffer[kBufferSize];
    char digit_buffer[30];
    int m_pos;
};

Reader f("rmq.in");
Writer g("rmq.out");

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) {
  int i, a, b, pass = 0;
  f>>N>>M;
  int sq = sqrt(N);

  lg[1] = 0;
  for (i = 0; i < N; i++) {
    f>>val[i];
    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) {
    f>>a>>b;

    --a; --b;

    tmp = a / sq;
    pass = b / sq;
    if (tmp == pass) {
      g<<naive(a, b)<<"\n";
    } else {
      g<<(MIN(left[b], MIN(right[a], look(tmp + 1, pass - 1))))<<"\n";
    }
    M--;
  }

  return 0;
}