Cod sursa(job #711789)

Utilizator mottyMatei-Dan Epure motty Data 12 martie 2012 19:41:28
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.16 kb
#include <fstream>
#include <cstdlib>
#include <cstring>

using namespace std;

ifstream in("rmq.in");
ofstream out("rmq.out");

const int N = 100001;
const int sqrtN = 320;

int n, lim, m;

int v[N];
int am[N]; // alma mater
int pp[N]; // position in piece

int best[sqrtN][sqrtN]; // best on i-j pieces
int bTo[sqrtN][sqrtN]; // best in piece i to j
int bFrom[sqrtN][sqrtN]; // best in piece i from j

void read()
{
    in >> n >> m;

    for (int i = 1; i <= n; ++i)
        in >> v[i];
}

inline int getSqrt(int value)
{
    int i;
    for (i = 1; i * i < value; ++i);
    return i;
}

inline int GetMin(int a, int b)
{
    return (a<b ? a:b);
}

inline int GetMin(int a, int b, int c)
{
    return GetMin(a, GetMin(b, c));
}

void makeBest()
{
    for (int dist = 1; dist <= lim; ++dist)
        for (int i = 1; i + dist <= lim; ++i)
            best[i][i+dist] = GetMin(best[i][i+dist-1], best[i+1][i+dist]);
}

void initialize()
{
    memset(best, 0x3f3f3f3f, sizeof(best));
    memset(bTo, 0x3f3f3f3f, sizeof(bTo));
    memset(bFrom, 0x3f3f3f3f, sizeof(bFrom));
    lim = getSqrt(n);

    for (int piece = 1; piece <= lim; ++piece) {
        int almaMater = (piece - 1)*lim;

        for (int pos = almaMater + 1; pos <= almaMater + lim && pos <= n; ++pos) {
            pp[pos] = pos - almaMater;
            am[pos] = piece;
            bTo[piece][pp[pos]] = GetMin(bTo[piece][pp[pos]-1], v[pos]);
        }

        for (int pos = GetMin(almaMater + lim, n); pos > almaMater; --pos) {
            bFrom[piece][pp[pos]] = GetMin(bFrom[piece][pp[pos]+1], v[pos]);
        }

        best[piece][piece] = bFrom[piece][1];
    }
}

int getMiniAnswer(int a, int b)
{
    int minim = 0x3f3f3f3f;

    for (int i = a; i <= b; ++i)
        if (v[i] < minim)
            minim = v[i];

    return minim;
}

void answerQueries()
{
    while (m--) {
        int a, b;
        in >> a >> b;

        if (am[a] == am[b]) // Sunt din aceeasi bucata
            out << getMiniAnswer(a, b) << "\n";
        else
            out << GetMin(best[am[a] + 1][am[b] - 1], bTo[am[b]][pp[b]], bFrom[am[a]][pp[a]]) << "\n";
    }
}

int main()
{
    read();
    initialize();
    makeBest();
    answerQueries();

    return 0;
}