Cod sursa(job #2754715)

Utilizator Rares5000Baciu Rares Rares5000 Data 26 mai 2021 13:16:30
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.27 kb
#include <bits/stdc++.h>
using namespace std;

/**
Range Minumum Query

Se da un sir a1, a2, ..., an (n <= 100.000)
Se dau m (m<=10^6)intrebari, fiecare intrebare fiind data
de o pereche (i,j): care este val. maxima din
a[i], a[i+1], ..., a[j]?

Sol:
Aflam valorile maxime pe orice interval
de lungime o putere a lui 2.

Pp. ca avem o functie f(i, j) care furnizeaza
val maxima de pe intervalul [i,j] care este de
lungime o putere a lui 2.

f(5,8) pot calcula
f(5,9) nu pot

max(a[6], a[7], ..., a[60])
= max(f(6,37), f(38,53), f(54,57), f(58,59), f(60,60))
= max(f(6,37), f(29,60))

a = 6,3,7,8,2,30,5,1,4
      3,7,8,2 = 8
      2,30,5,1 = 30
*/

class RMQ
{
public:
    int rmq[18][100002];
    /// rmq[i][j] = val minima pe intervalul
    /// de lungime 2^i care incepe la pozitia j
    int e[100002];
    /// e[i] = exponentul maxim al lui 2
    /// cu prop. ca 2^e[i]<=i
    int n;

public:
    void Init(int dim)
    {
        n = dim;
    }

    friend istream& operator>>(istream& in, RMQ& A)
    {
        in >> A.n;
        for (int i = 1; i <= A.n; i++)
            in >> A.rmq[0][i];
        return in;
    }

    void ConstructieE()
    {
        ///     1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
        /// e = 0 1 1 2 2 2 2 3 3 3   3  3  3  3  3  4  4

        e[1] = 0;
        for (int i = 2; i <= n; i++)
            e[i] = 1 + e[i / 2];
    }

    void ConstrMat()
    {
        int i, j;
        for (i = 1; i <= e[n]; i++)
            for (j = 1; j <= n - (1 << i) + 1; j++)
                rmq[i][j] = min(rmq[i-1][j],
                    rmq[i-1][j+(1<<(i-1))]);
    }

    int ValMin(int x, int y)
    {
        int expo = e[y - x + 1];
        int L = (1 << expo);
        return min(rmq[expo][x], rmq[expo][y - L + 1]);
    }
};
ifstream fin("rmq.in");
ofstream fout("rmq.out");
int main()
{
    int Q = 0, x, y, dim;
    RMQ A;
    fin >> dim >> Q;
    A.Init(dim);
    for (int i = 1; i <= A.n; i++)
    {
        fin >> x;
        A.rmq[0][i] = x;
    }

    A.ConstructieE();
    A.ConstrMat();

    for (int i = 1; i <= Q; i++)
    {
        fin >> x >> y;
        fout << A.ValMin(x, y) << "\n";
    }
    /// Complexitate O(n + n + nlogn + Q)
    fout.close();
    return 0;
}