Pagini recente » Cod sursa (job #2369732) | Cod sursa (job #3255024) | Cod sursa (job #1453899) | Betasah | Cod sursa (job #2751280)
#include <iostream>
#include <fstream>
#include <cmath>
std::ifstream f("rmq.in");
std::ofstream g("rmq.out");
int logaritm[100001],n,m;
// sparse table -> tbl[i][j] = minimul din secv care incepe la poz i si e de lungime 2^j
int tbl[100001][20]; // log2(100000) ~ 20
int query(int left, int right)
{
int log = logaritm[right - left + 1]; // iau cea mai mare putere a lui 2 mai mica sau egala cu lungimea query-ului
// [ 1, 2, 3, 4, 5 ] aici log = 2
// |________|
// |_________| => minimul dintre 1-6 e minimul dintre 1-4 si 3-6, deci pt orice query ma folosesc doar de 2 secv => O(1) pe query
return std::min(tbl[left][log], tbl[right - (1 << log) + 1][log]);
}
int main()
{
f >> n >> m;
// minimul din secv care incepe la i si e de lungime 1 (adica 2^0) e chiar elementul de pe poz i
for (int i = 1; i <= n; ++i)
{
f >> tbl[i][0];
}
for (int i = 2; i <= n; ++i)
logaritm[i] = 1 + logaritm[i / 2]; // calculez partea intreaga din log2 din toate nr de la 1 la n (pt query)
for (int j = 1; j <= logaritm[n]; ++j)
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
tbl[i][j] = std::min(tbl[i][j - 1], tbl[i + (1 << (j-1))][j - 1]);
// minimul din secventa care incepe la i si e de lungime 2^j este minimul dintre cele 2 jumatati de lungime 2^(j-1):
// minimul din secventa care incepe la i si e de lungime 2^(j-1) si
// minimul din secventa care incepe de la i + 2^(j-1) si e de lungime 2^(j-1)
// [1, 2, 3, 4, 5, 6, 7, 8]
// |_________| |________|
// |____________________|
// min dintre secv 1-8 e min( minim din secv 1-4, minim din secv 5-8)
int x, y;
for (int i = 0; i < m; ++i)
{
f >> x >> y;
g << query(x, y) << '\n';
}
}