Pagini recente » Cod sursa (job #3142562) | Cod sursa (job #2284410) | Cod sursa (job #3185837)
#include <fstream>
#include <vector>
using namespace std;
ifstream f("rmq.in");
ofstream g("rmq.out");
/// Arbori de intervale - complexitate O(log n) per query
/// RMQ - putem folosi cand nu avem update-uri, cand intervalele se pot intersecta fara sa incurce
/// rezultatul si avem O(1) per query, O(n log n) la constructie
int n, m, x, y, l, a, b;
int k[100005], kcurent;
pair < int, int > rmq[200005][25]; /// rmq[n][log n]
vector < int > v[100005];
pair < int, int > euler[200005]; /// 2*n => perechi de tipul {nivel, nod}
int ctr;
int prap[100005]; /// prima aparitie a fiecarui nod in reprezentarea euler
void dfs(int nivel, int nod) {
euler[++ctr] = { nivel, nod };
prap[nod] = ctr;
for (auto newnod : v[nod]) {
dfs(nivel + 1, newnod);
euler[++ctr] = { nivel, nod };
}
}
void create_rmq() {
/// un rmq pe reprezentarea euler
for (int j = 0; (1 << j) <= ctr; j++) {
for (int i = 1; i + (1 << j) - 1 <= ctr; i++) {
if (j == 0) {
rmq[i][j] = euler[i];
}
else {
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
}
}
}
void solve() {
for (int i = 2; i <= ctr; i++) {
k[i] = k[i - 1];
if ((1 << (k[i] + 1)) < i) {
k[i]++;
}
}
for (int t = 1; t <= m; t++) {
f >> a >> b;
x = prap[a]; y = prap[b];
l = y - x + 1; /// lungimea intervalului
g << min(rmq[x][k[l]], rmq[y-(1<<k[l])+1][k[l]]).second << '\n';
/// .first = nivelul , .second = nodul
}
}
int main()
{
f >> n >> m;
for (int i = 2; i <= n; i++) {
f >> x;
v[x].push_back(i);
}
dfs(0, 1); /// radacina = 1 , pe nivelul 0
create_rmq();
solve();
}