Pagini recente » Cod sursa (job #3236941) | Autentificare | Cod sursa (job #2063723) | Cod sursa (job #502127) | Cod sursa (job #2521499)
//package main;
import java.io.*;
import java.util.ArrayList;
public class Main {
ArrayList<Integer>[] g;
int[] rmqDepth;
int[][] rmq;
int[] euler;
int[] depth;
int eulerIndex;
int[] parent;
int[] first;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("lca.in"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("lca.out")));
Main app = new Main();
app.solve(br, pw, 1);
pw.close();
}
private void solve(BufferedReader br, PrintWriter pw, int caseNumber) throws IOException {
String str2 = br.readLine();
String[] splitString2 = str2.split(" ");
int N = Integer.parseInt(splitString2[0]);
int Q = Integer.parseInt(splitString2[1]);
g = new ArrayList[N + 1];
for (int j = 1; j <= N; j++) {
g[j] = new ArrayList<Integer>();
}
parent = new int[N + 1];
String str3 = br.readLine();
String[] splitString3 = str3.split(" ");
for (int j = 0; j < N - 1; j++) {
int father = Integer.parseInt(splitString3[j]);
g[father].add(j + 2);
parent[j + 2] = father;
}
//precompute depths of nodes
int root = 1;
first = new int[N + 1];
euler = new int[2 * N - 1];
depth = new int[N + 1];
eulerIndex = 0;
eulerFlatTree(root, 0);
//find the depths of order
rmqDepth = new int[euler.length];
for (int l = 0; l < euler.length; l++) {
rmqDepth[l] = depth[euler[l]];
}
//precompute rmq values
rmqPrecompute();
for (int q = 0; q < Q; q++) {
String str5 = br.readLine();
String[] splitString5 = str5.split(" ");
//System.out.println(Integer.parseInt(splitString5[0]));
int fromEulerIndex = first[Integer.parseInt(splitString5[0])];
//System.out.println(Integer.parseInt(splitString5[1]));
int toEulerIndex = first[Integer.parseInt(splitString5[1])];
//System.out.println("From " + fromEulerIndex + " to " + toEulerIndex);
if(fromEulerIndex > toEulerIndex) {
int auz = fromEulerIndex;
fromEulerIndex = toEulerIndex;
toEulerIndex = auz;
}
int ans = rmqQuery(fromEulerIndex, toEulerIndex);
//System.out.println("Euler[ans] " + euler[ans] + " ans " + ans);
pw.println(euler[ans]);
}
}
public int rmqQuery(int from, int to) {
int diff = to - from + 1;
int pow2diff = 1;
int exp2 = 0;
while (2 * pow2diff <= diff) {
pow2diff *= 2;
exp2++;
}
int tob = from + pow2diff - 1;
int fromb = to - pow2diff + 1;
//System.out.println(fromb + " " + exp2);
int answer = Math.min(rmqDepth[rmq[from][exp2]], rmqDepth[rmq[fromb][exp2]]);
if (answer == rmqDepth[rmq[from][exp2]]) {
return rmq[from][exp2];
}
return rmq[fromb][exp2];
}
public void rmqPrecompute() {
int n = rmqDepth.length;
int log2 = 1;
while((1<<log2) <= n)
log2++;
rmq = new int[n][log2];
for (int i = 0; i < n; i++) {
rmq[i][0] = i;
}
for (int k = 1; (1 << k) < n; k++) {
for (int i = 0; i + (1 << k) - 1 < n; i++) {
int answer = Math.min(rmqDepth[rmq[i][k - 1]], rmqDepth[rmq[i + (1 << (k - 1))][k - 1]]);
if (answer == rmqDepth[rmq[i][k - 1]]) {
rmq[i][k] = rmq[i][k - 1];
} else {
rmq[i][k] = rmq[i + (1 << (k - 1))][k - 1];
}
}
}
}
public void eulerFlatTree(int node, int currentDepth) {
first[node] = eulerIndex;
euler[eulerIndex] = node;
eulerIndex++;
depth[node] = currentDepth;
for (int sons : g[node]) {
eulerFlatTree(sons, currentDepth + 1);
euler[eulerIndex] = node;
eulerIndex++;
}
}
}