Pagini recente » Cod sursa (job #3282048) | Cod sursa (job #1361921)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
class Node {
private final int index;
private final Node father;
private final List<Node> children;
Node(Node father, int index) {
this.index = index;
this.father = father;
this.children = new ArrayList<Node>();
}
void addChild(Node node) {
this.children.add(node);
}
Node getFather() {
return father;
}
int getIndex() {
return index;
}
List<Node> getChildren() {
return children;
}
}
class LCAFinder {
private final List<Node> nodes;
private final List<Integer> euler = new ArrayList<Integer>();
private List<List<Integer>> rmq = new ArrayList<List<Integer>>();
private int iter = -1;
private Map<Node, Integer> first = new HashMap<Node, Integer>();
private Map<Integer, Node> positions = new HashMap<Integer, Node>();
private List<Integer> powers = new ArrayList<Integer>();
public LCAFinder(List<Node> nodes) {
this.nodes = nodes;
precomputeLCAs();
}
private void precomputeLCAs() {
euler(nodes.get(0));
rmq();
}
private void euler(Node node) {
int order = ++iter;
first.put(node, euler.size());
positions.put(order, node);
euler.add(order);
for (Node child : node.getChildren()) {
euler(child);
euler.add(order);
}
}
private void rmq() {
int N = euler.size();
powers.add(0);
// Set the powers of 2 for all lengths.
for (int l = 0; (1 << l) <= N; ++l) {
for (int i = (1 << l); i < (1 << (l + 1)); ++i) {
powers.add(l);
}
}
// Make RMQ[0].
rmq.add(euler);
// Make RMQ[i] using RMQ[i - 1].
for (int l = 1; (1 << l) <= N; ++l) {
List<Integer> rmqi = new ArrayList<Integer>();
for (int i = 0; i + (1 << l) <= N; ++i) {
int left = rmq.get(l - 1).get(i);
int right = rmq.get(l - 1).get(i + (1 << (l - 1)));
rmqi.add(Math.min(left, right));
}
rmq.add(rmqi);
}
}
public int findLCA(int x, int y) {
int firstX = first.get(nodes.get(x));
int firstY = first.get(nodes.get(y));
int min = Math.min(firstX, firstY);
int max = Math.max(firstX, firstY);
firstX = min;
firstY = max;
int dist = firstY - firstX + 1;
int l = powers.get(dist);
int left = rmq.get(l).get(firstX);
int right = rmq.get(l).get(firstY - (1 << l) + 1);
int pos = Math.min(left, right);
return positions.get(pos).getIndex();
}
}
public class Main {
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("lca.in");
Scanner scanner = new Scanner(inputStream);
OutputStream outputStream = new FileOutputStream("lca.out");
PrintWriter writer = new PrintWriter(outputStream);
int N = scanner.nextInt();
int M = scanner.nextInt();
List<Node> nodes = new ArrayList<Node>();
nodes.add(new Node(null, 0));
for (int i = 1; i < N; ++i) {
int fatherIndex = scanner.nextInt() - 1;
Node father = nodes.get(fatherIndex);
Node node = new Node(father, i);
father.addChild(node);
nodes.add(node);
}
LCAFinder lcaFinder = new LCAFinder(nodes);
while (M-- > 0) {
int x = scanner.nextInt() - 1;
int y = scanner.nextInt() - 1;
int lca = lcaFinder.findLCA(x, y) + 1;
writer.println(lca);
}
writer.flush();
inputStream.close();
scanner.close();
outputStream.close();
writer.close();
}
}