Cod sursa(job #2518594)

Utilizator sratropSra Trop sratrop Data 6 ianuarie 2020 00:08:56
Problema Lowest Common Ancestor Scor 0
Compilator java Status done
Runda Arhiva educationala Marime 4.92 kb
package main;
	
 
	
import java.io.*;
	
import java.util.ArrayList;
	
 
	
public class lcainfoarena {
	
 
	
        ArrayList<Integer>[] g;
	
        int[] rmqDepth;
	
        int[][] rmq;
	
        int[] euler;
	
        int[] depth;
	
        int eulerIndex;
	
        int[] parent;
	
        int[] first;
	
 
	
        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);
	
                int ans = rmqQuery(fromEulerIndex, toEulerIndex);
	
                //System.out.println("Euler[ans] " + euler[ans] + " ans " + ans);
	
                pw.println(euler[ans]);
	
            }
	
 
	
 
	
        }
	
 
	
 
	
        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.lcainfoarena app = new main.lcainfoarena();
	
            app.solve(br, pw, 1);
	
 
	
            pw.close();
	
        }
	
 
	
        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;
	
            rmq = new int[n][n];
	
 
	
            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++;
	
 
	
            }
	
 
	
        }
	
 
	
 
	
    }