Pagini recente » Cod sursa (job #3151823) | Cod sursa (job #1527194) | Cod sursa (job #2966391) | Cod sursa (job #563256) | Cod sursa (job #3279305)
#include <bits/stdc++.h>
#pragma GCC optimize("O2")
std::ifstream fin("rmq.in");
std::ofstream fout("rmq.out");
/*
Pentru fiecare poziție i din v, vom calcula mai multe minime. Pentru fiecare
secvență de lungime putere de 2 care începe la poziția i, vom calcula minimul dintre
elementele ei. Deci, pentru fiecare poziție din v vom avea maximum log2 n minime de calculat (atâtea
puteri de 2 sunt mai mici sau egale cu n).
Astfel, vom obține o matrice r[p][i] = minimul din v pentru elementele dintr-o secvență
de lungime 2^p care începe la poziția i.
*/
const int size = 1e5 + 5;
const int p_max = 20;
int n, q, st, dr;
int a[size], E[size];
int rmq[p_max][size];
int main()
{
std::ios_base::sync_with_stdio(false);
fin.tie(nullptr);
fout.tie(nullptr);
// Obs: rmq[0][i] = min(i, i + 2^0 - 1) = min(i, i) = a[i]
fin >> n >> q;
for(int i = 1; i <= n; ++i)
{
fin >> a[i];
rmq[0][i] = a[i];
}
// Obs: rmq[p] depinde doar de rmq[p - 1], deci calculam liniile in ordine crescatoare
// Obs: rmq[p][i] = min(rmq[p - 1][i], rmq[p - 1][i + 2 ^ (p - 1)] (se observa usor)
for(int p = 1; (1 << p) <= n; ++p)
for(int i = 1; i <= n; ++i)
{
rmq[p][i] = rmq[p - 1][i];
int j = i + (1 << (p - 1));
if(j <= n)
rmq[p][i] = std::min(rmq[p][i], rmq[p - 1][j]);
}
// Obs: Pentru a raspunde la queries avem nevoie de o impartire a bucatii [st, dr] in 2 bucati de lungime
// egala cu o putere de 2. Fie 2^e = puterea de 2 maxima <= L (unde L este dr - st + 1, lungimea sirului)
// In acest fel putem descompune Q(st, dr) in min(rmq[e][st], rmq[e][dr - 2^e + 1])
// Tot ce ne mai trebuie este acel "e", cum il aflam? Cu ajutorul unei precalculari!
E[1] = 0;
for(int i = 2; i <= n; ++i)
E[i] = 1 + E[i / 2];
while(q--)
{
fin >> st >> dr;
int e = E[dr - st + 1];
int ans = std::min(rmq[e][st], rmq[e][dr - (1 << e) + 1]);
fout << ans << "\n";
}
return 0;
}