Cod sursa(job #2520985)

Utilizator sratropSra Trop sratrop Data 10 ianuarie 2020 03:49:25
Problema Lowest Common Ancestor Scor 0
Compilator java Status done
Runda Arhiva educationala Marime 4.3 kb
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;

        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 app = new Main();
            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++;

            }

        }


    }