Pagini recente » Cod sursa (job #2299800) | Cod sursa (job #219120) | Cod sursa (job #382935) | Cod sursa (job #1388452) | Cod sursa (job #1067506)
#include <fstream>
#include <utility>
#include <vector>
#include <climits>
class LCA {
struct Vertex {
int apar;
std::vector<int> myL;
Vertex() : apar(-1), myL() {}
};
struct Euler {
int node, lvl;
Euler() : node(), lvl() {}
Euler(int a, int b) : node(a), lvl(b) {}
};
int nV, back, *log, **RMQ;
Vertex *myG;
Euler *myV;
void dfa(int nod, int level) {
myV[++back] = Euler(nod, level);
myG[nod].apar = back;
for(auto it = myG[nod].myL.begin(); it != myG[nod].myL.end(); it++) {
dfa(*it, level + 1);
myV[++back] = Euler(nod, level);
}
}
public:
LCA(int a) : nV(a), back(), myG(new Vertex[a + 1]), myV(new Euler[a << 1]) {
myV[0] = Euler(INT_MAX, INT_MAX);
for(int i = 0; i <= a; i++) {
myG[i] = Vertex();
}
}
~LCA() {
delete[] myG;
delete[] myV;
delete[] log;
for(int i = 0; i <= back; i++) {
delete[] RMQ[i];
}
delete[] RMQ;
}
void pushEdge(int a, int b) {
myG[a].myL.push_back(b);
}
void start() {
dfa(1, 0);
log = new int[back + 1];
log[1] = 0;
for(int i = 2; i <= back; i++) {
log[i] = log[i >> 1] + 1;
}
RMQ = new int*[back + 1];
for(int i = 0; i <= back; i++) {
RMQ[i] = new int[log[back] + 1];
}
for(int i = 0; i <= back; i++) {
for(int j = 0; j <= log[back]; j++) {
RMQ[i][j] = 0;
}
}
for(int i = 1; i <= back; i++) {
RMQ[i][0] = i;
}
for(int j = 1; (1 << j) <= back; j++) {
for(int i = 1; i + (1 << j) - 1 <= back; i++) {
int aux = 1 << (j - 1);
if(myV[RMQ[i][j - 1]].lvl > myV[RMQ[i + aux][j - 1]].lvl) {
RMQ[i][j] = RMQ[i + aux][j - 1];
} else {
RMQ[i][j] = RMQ[i][j - 1];
}
}
}
}
int query(int x, int y) {
int a = myG[x].apar, b = myG[y].apar;
if(a > b) {
return query(y, x);
}
int aux = b - a + 1;
int loga = log[aux];
int search = aux - (1 << loga);
int sol;
if(myV[RMQ[a][loga]].lvl > myV[RMQ[a + search][loga]].lvl) {
sol = myV[RMQ[a + search][loga]].node;
} else {
sol = myV[RMQ[a][loga]].node;
}
return sol;
}
};
int main() {
std::ifstream in("lca.in");
std::ofstream out("lca.out");
int nV, nOp, x, y;
in >> nV >> nOp;
LCA a(nV);
for(int i = 2; i <= nV; i++) {
in >> x;
a.pushEdge(x, i);
}
a.start();
for(int i = 0; i < nOp; i++) {
in >> x >> y;
out << a.query(x, y) << '\n';
}
return 0;
}