Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.io.PrintWriter;
- import java.util.ArrayList;
- /**
- * Created by aleksandr on 25.10.16.
- */
- class SegmentTree {
- class SegmentPair {
- int value;
- int index;
- SegmentPair(int val, int ind) {
- value = val;
- index = ind;
- }
- }
- SegmentPair min(SegmentPair a, SegmentPair b) {
- if (a.value < b.value) {
- return a;
- } else return b;
- }
- ArrayList<SegmentPair> segmTree;
- private int closestTwoPow(int n) {
- for (int i = 0; ; i++) {
- if (Math.pow(2, i) >= n)
- return (int) Math.pow(2, i);
- }
- }
- SegmentTree(ArrayList<Integer> basicArray) {
- //building segment tree for range minimum query
- int newSize = closestTwoPow(basicArray.size());
- segmTree = new ArrayList<SegmentPair>(newSize * 2 - 1);
- //tmp wtf
- for (int i = 0; i < newSize * 2 - 1; i++)
- segmTree.add(new SegmentPair(0, 0));
- for (int i = segmTree.size() - newSize; i < segmTree.size() - newSize + basicArray.size(); i++) {
- segmTree.set(i, new SegmentPair(basicArray.get(i - newSize + 1), i - newSize + 1));
- }
- for (int i = segmTree.size() - newSize + basicArray.size(); i < segmTree.size(); i++) {
- segmTree.set(i, new SegmentPair(Integer.MAX_VALUE, 0));
- }
- for (int i = segmTree.size() - 1 - newSize; i >= 0; i--) {
- segmTree.set(i, min(segmTree.get(2 * i + 1), segmTree.get(2 * i + 2)));
- }
- //segment tree for given array built successfully
- }
- //pre:
- // indices are accepted in base array, not in segmTree array
- //post:
- // returns index of minimal element in range
- public int rangeMinQuery(int l, int r) {
- //we have to find minimum on the range from l to r indices in array
- l += segmTree.size() / 2;
- r += segmTree.size() / 2;
- SegmentPair ans = new SegmentPair(Integer.MAX_VALUE, 0);
- while (true) {
- //if l is right child
- if (l / 2 - 1 == (l - 1) / 2) {
- ans = min(ans, segmTree.get(l));
- l++;
- }
- //if r is left child
- if (r / 2 - 1 != (r - 1) / 2) {
- ans = min(ans, segmTree.get(r));
- r--;
- }
- if (r < l) break;
- //going one level up:
- if (l / 2 - 1 != (l - 1) / 2) {
- l = l / 2;
- } else {
- l = l / 2 - 1;
- }
- if (r / 2 - 1 != (r - 1) / 2) {
- r = r / 2;
- } else {
- r = r / 2 - 1;
- }
- }
- return ans.index;
- }
- }
- class Tree {
- class Node {
- int number;
- ArrayList<Node> children;
- Node(int num) {
- number = num;
- children = new ArrayList<Node>();
- }
- }
- Node root;
- ArrayList<Node> arrNodes;
- ArrayList<Integer> numberNode;
- ArrayList<Integer> depthNode;
- ArrayList<Integer> indexesNode;
- //reads input and builds a tree
- Tree(BufferedReader br) throws Exception {
- String str;
- int n = Integer.parseInt(br.readLine());
- arrNodes = new ArrayList<Node>();
- root = new Node(1);
- arrNodes.add(root);//adding root with no parent
- for (int i = 2; i <= n; i++) {
- Node tmp = new Node(i);
- arrNodes.add(tmp);
- arrNodes.get(Integer.parseInt(br.readLine()) - 1).children.add(tmp);
- }
- //tree built from input
- }
- void eulerTrip() {
- numberNode = new ArrayList<Integer>();
- depthNode = new ArrayList<Integer>();
- indexesNode = new ArrayList<Integer>();
- for (int i = 0; i < arrNodes.size(); i++) // resize
- indexesNode.add(0);
- recursiveTrip(this.root, 1);
- }
- void recursiveTrip(Node nod, int currentDepth) {
- indexesNode.set(nod.number - 1, numberNode.size());
- for (int i = 0; i < nod.children.size(); i++) {
- numberNode.add(nod.number);
- depthNode.add(currentDepth);
- recursiveTrip(nod.children.get(i), currentDepth + 1);
- }
- numberNode.add(nod.number);
- depthNode.add(currentDepth);
- }
- }
- public class LcaRmq {
- public static void main(String[] args) throws Exception {
- final String input = "lca.in";
- final String output = "lca.out";
- BufferedReader br = new BufferedReader(new FileReader(input));
- Tree tr = new Tree(br);
- tr.eulerTrip();
- int m = Integer.parseInt(br.readLine());
- SegmentTree st = new SegmentTree(tr.depthNode);
- PrintWriter writer = new PrintWriter(output);
- for (int i = 0; i < m; i++) {
- String[] parts = br.readLine().split(" ");
- int firstNodeIndexInArrayOfDepths = tr.indexesNode.get(Integer.parseInt(parts[0]) - 1);
- int secondNodeIndexInArrayOfDepths = tr.indexesNode.get(Integer.parseInt(parts[1]) - 1);
- if(firstNodeIndexInArrayOfDepths > secondNodeIndexInArrayOfDepths)
- {
- //swap wtf
- int tmp = secondNodeIndexInArrayOfDepths;
- secondNodeIndexInArrayOfDepths = firstNodeIndexInArrayOfDepths;
- firstNodeIndexInArrayOfDepths = tmp;
- }
- writer.println(tr.numberNode.get(st.rangeMinQuery(firstNodeIndexInArrayOfDepths, secondNodeIndexInArrayOfDepths)));
- }
- writer.close();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement