Schieber-Vishkin algorithm

The Schieber-Vishkin algorithm is a parallel algorithm for finding the lowest common ancestor (LCA) of two nodes in a tree. It operates in the concurrent-read exclusive-write (CREW) PRAM model and is notable for its efficiency, achieving logarithmic time complexity. The algorithm preprocesses the tree in time and allows subsequent LCA queries to be answered in time.

Task
Schieber-Vishkin algorithm
You are encouraged to solve this task according to the task description, using any language you may know.
Problem definition

The lowest common ancestor problem is defined as follows:

Given a rooted tree with nodes, and two nodes and in the tree, find the deepest node that is an ancestor of both and . Formally, satisfies:

and for any other node in the intersection:

Input

1. A rooted tree , where is the set of nodes and is the set of edges. The tree has nodes. 2. A pair of nodes , where .

Output

The algorithm outputs the node that is the lowest common ancestor of and .

Algorithm overview

The Schieber-Vishkin algorithm is designed to preprocess the tree in parallel to enable constant-time LCA queries. The preprocessing involves assigning each node a label that encodes information about its position in the tree hierarchy. These labels are constructed using tree structures such as parent-child relationships and depth.

The key steps of the algorithm are:

1. Tree representation: The input tree is represented as an adjacency list or similar structure. The root node is identified. 2. Preprocessing in parallel: During preprocessing:

  - Nodes are assigned labels based on their position in the tree.
  - Depth-first search (DFS) or similar traversal techniques are used to compute necessary information.

3. Query resolution: Using the precomputed labels, the LCA of any two nodes and can be determined in time.

Complexity

- Preprocessing time: using processors in the CREW PRAM model. - Query time: . - Space complexity: .

Applications

The Schieber-Vishkin algorithm is widely used in applications where fast query resolution is critical, such as:

- Network routing and communication. - Computational biology, particularly in phylogenetics. - Query optimization in databases. - Text processing, such as suffix tree and suffix array construction.

This algorithm is a foundational result in parallel computing and demonstrates how preprocessing can enable efficient query answering in tree-based problems.

// Compilation command: g++ -std=c++20 -Wall -Wextra -pedantic SchieberVishkinAlgorithm.cpp -o SchieberVishkinAlgorithm

#include <algorithm>
#include <array>
#include <bit>
#include <cassert>
#include <iostream>
#include <limits>
#include <span>
#include <stack>
#include <vector>

struct Node {
    int child = 0;
    int sibling = 0;
    int parent = 0;
};

struct LCAData {
    std::vector<int> pi;
    std::vector<int> beta;
    std::vector<int> alpha;
    std::vector<int> tau;
    std::vector<int> lambda;
};

bool traversalPhase(
    int &p, int &time,
    std::vector<int> &pi,
    std::vector<int> &beta,
    std::vector<int> &tau,
    std::vector<int> &lambda,
    const std::vector<Node> &nodes
) {
    while (true) {
        ++time;
        pi[p] = time;
        tau[time] = 0;
        lambda[time] = 1 + lambda[time>>1];
        if (nodes[p].child != 0) {
            p = nodes[p].child;
            continue;
        }
        beta[p] = time;
        break;
    }
    while (true) {
        tau[beta[p]] = nodes[p].parent;
        if (nodes[p].sibling != 0) {
            p = nodes[p].sibling;
            return true;
        }
        p = nodes[p].parent;
        if (p != 0) {
            int w = time & -pi[p];
            int h = lambda[w];
            beta[p] = ((time >> h) | 1) << h;
        } else
            return false;
    }
}

void computeAlpha(
    const std::vector<Node> &nodes,
    int root,
    std::vector<int> &alpha,
    const std::vector<int> &beta
) {
    std::stack<int> stk;
    stk.push(root);
    while (!stk.empty()) {
        int u = stk.top(); stk.pop();
        alpha[u] = alpha[nodes[u].parent] | (beta[u] & -beta[u]);
        if (nodes[u].sibling)
            stk.push(nodes[u].sibling);
        if (nodes[u].child)
            stk.push(nodes[u].child);
    }
}

LCAData buildLCAData(int N, const std::vector<int>& A) {
    LCAData D;
    D.pi.assign(N+1, 0);
    D.beta.assign(N+1, 0);
    D.alpha.assign(N+1, 0);
    D.tau.assign(N+1, 0);
    D.lambda.assign(N+1, 0);

    std::vector<Node> nodes(N + 1);
    int t = 0;
    for (int v = N; v > 0; --v) {
        int u = 0;
        while (A[v] > A[t] || (A[v] == A[t] && v > t)) {
            u = t;
            t = nodes[t].parent;
        }
        if (u) {
            nodes[v].sibling = nodes[u].sibling;
            nodes[u].sibling = 0;
            nodes[u].parent = v;
            nodes[v].child = u;
        } else
            nodes[v].sibling = nodes[t].child;
        nodes[t].child = v;
        nodes[v].parent = t;
        t = v;
    }

    int p = nodes[0].child;
    int time = 0;
    D.lambda[0] = -1;
    while (traversalPhase(p, time, D.pi, D.beta, D.tau, D.lambda, nodes));

    p = nodes[0].child;
    D.lambda[0] = D.lambda[time];
    D.pi[0] = D.beta[0] = D.alpha[0] = 0;
    if (p)
        computeAlpha(nodes, p, D.alpha, D.beta);
    return D;
}

int nca(int x, int y, const LCAData& D) {
    unsigned bx = static_cast<unsigned>(D.beta[x]);
    unsigned by = static_cast<unsigned>(D.beta[y]);
    unsigned b = (bx <= by) ? (by & -bx) : (bx & -by);
    if (b == 0)
        return D.pi[x] <= D.pi[y] ? x : y;
    int h = std::countr_zero(b);

    unsigned ax = static_cast<unsigned>(D.alpha[x]);
    unsigned ay = static_cast<unsigned>(D.alpha[y]);
    unsigned k = ax & ay & ~((~0u) << h);
    if (k == 0)
        return D.pi[x] <= D.pi[y] ? x : y;
    h = std::countr_zero(k);

    int jx = (((D.beta[x] >> h) | 1) << h);
    if (jx != D.beta[x]) {
        unsigned lmask = static_cast<unsigned>(D.alpha[x]) & ((1u << h) - 1u);
        if (lmask) {
            int l = std::countr_zero(lmask);
            x = D.tau[(((D.beta[x] >> l) | 1) << l)];
        }
    }
    int jy = (((D.beta[y] >> h) | 1) << h);
    if (jy != D.beta[y]) {
        unsigned lmask = static_cast<unsigned>(D.alpha[y]) & ((1u << h) - 1u);
        if (lmask) {
            int l = std::countr_zero(lmask);
            y = D.tau[(((D.beta[y] >> l) | 1) << l)];
        }
    }
    return D.pi[x] <= D.pi[y] ? x : y;
}

std::vector<int> solveTestCase(
    const std::vector<int> &values,
    const std::vector<std::array<int, 2>> &queries
) {
    int n = int(values.size());
    std::vector<int> A(n+2), R(n+2), B(n+2);
    A[0] = std::numeric_limits<int>::max();
    int N = 1, cnt = 0;
    for (int i = 1; i <= n; ++i) {
        if (i > 1 && values[i-1] != values[i-2]) {
            A[N] = cnt;
            R[N] = i;
            ++N;
            cnt = 0;
        }
        B[i] = N;
        ++cnt;
    }
    A[N] = cnt;
    R[N] = n + 1;

    LCAData D = buildLCAData(N, A);
    std::vector<int> ans;
    ans.reserve(queries.size());
    for (auto [i, j] : queries) {
        int x = B[i], y = B[j];
        int z;
        if (x == y)
            z = j - i + 1;
        else {
            int mid = (x + 1 < y) ? A[nca(x+1, y-1, D)] : 0;
            z = std::max({mid, R[x]-i, A[y]-(R[y]-j)+1});
        }
        ans.push_back(z);
    }
    return ans;
}

int main() {
    std::vector<int> values = {-1, -1, 1, 1, 1, 1, 3, 10, 10, 10};
    std::vector<std::array<int, 2>> queries = {{2, 3}, {1, 10}, {5, 10}};
    std::vector<int> expected = {1, 4, 3};
    auto result = solveTestCase(values, queries);
    assert(result == expected);
    std::cout << "All tests passed.\n";
    return 0;
}
Works with: C# version 8.0
Translation of: Java
using System;
using System.Collections.Generic;

class Program
{
    static Result Process(int N, int[] A)
    {
        int[] pi = new int[N + 1];
        int[] beta = new int[N + 1];
        int[] alfa = new int[N + 1];
        int[] tau = new int[N + 1];
        int[] lam = new int[N + 1];
        Node[] nodes = new Node[N + 1];
        for (int i = 0; i <= N; i++)
        {
            nodes[i] = new Node();
        }
        
        // Make triply linked tree
        int t = 0;
        for (int v = N; v > 0; v--)
        {
            int u = 0;
            while (A[v] > A[t] || (A[v] == A[t] && v > t))
            {
                u = t;
                t = nodes[t].Parent;
            }
            
            if (u != 0)
            {
                nodes[v].Sib = nodes[u].Sib;
                nodes[u].Sib = 0;
                nodes[u].Parent = v;
                nodes[v].Child = u;
            }
            else
            {
                nodes[v].Sib = nodes[t].Child;
            }
            
            nodes[t].Child = v;
            nodes[v].Parent = t;
            t = v;
        }
        
        // Begin first traversal
        int p = nodes[0].Child;
        int n = 0;
        lam[0] = -1;
        
        while (Traversal(nodes, p, n, pi, beta, tau, lam, out p, out n))
        {
            // Continue traversal
        }
        
        // Begin second traversal
        p = nodes[0].Child;
        lam[0] = lam[n];
        pi[0] = beta[0] = alfa[0] = 0;
        
        // Perform second traversal
        if (p != 0)
        {
            ComputeAlfa(nodes, p, alfa, beta);
        }
        
        return new Result(pi, beta, alfa, tau, lam);
    }
    
    static bool Traversal(Node[] nodes, int initialP, int initialN, int[] pi, int[] beta, int[] tau, int[] lam, out int newP, out int newN)
    {
        int p = initialP;
        int n = initialN;
        
        // s3: Compute beta in the easy case
        while (true)
        {
            n++;
            pi[p] = n;
            tau[n] = 0;
            lam[n] = 1 + lam[n >> 1];
            
            if (nodes[p].Child != 0)
            {
                p = nodes[p].Child;
                continue;
            }
            
            beta[p] = n;
            break;
        }
        
        // s4: Compute tau, bottom-up
        while (true)
        {
            tau[beta[p]] = nodes[p].Parent;
            
            if (nodes[p].Sib != 0)
            {
                p = nodes[p].Sib;
                newP = p;
                newN = n;
                return true;  // Go back to s3
            }
            
            p = nodes[p].Parent;
            
            // Compute beta in the hard case
            if (p != 0)
            {
                int h = lam[n & -pi[p]];
                beta[p] = ((n >> h) | 1) << h;
            }
            else
            {
                newP = p;
                newN = n;
                return false;  // Exit traversal
            }
        }
    }
    
    static void ComputeAlfa(Node[] nodes, int node, int[] alfa, int[] beta)
    {
        // s7: Compute alfa, top-down
        alfa[node] = alfa[nodes[node].Parent] | (beta[node] & -beta[node]);
        
        if (nodes[node].Child != 0)
        {
            ComputeAlfa(nodes, nodes[node].Child, alfa, beta);
        }
        
        // s8: Continue traversal
        if (nodes[node].Sib != 0)
        {
            ComputeAlfa(nodes, nodes[node].Sib, alfa, beta);
        }
    }
    
    static int Nca(int x, int y, int[] beta, int[] alfa, int[] tau, int[] lam, int[] pi)
    {
        // Find common height
        int h;
        if (beta[x] <= beta[y])
        {
            h = lam[beta[y] & -beta[x]];
        }
        else
        {
            h = lam[beta[x] & -beta[y]];
        }
        
        // Find true height
        int k = alfa[x] & alfa[y] & -(1 << h);
        h = lam[k & -k];
        
        // Find beta[z]
        int j = ((beta[x] >> h) | 1) << h;
        
        // Find x' and y'
        if (j != beta[x])
        {
            int l = lam[alfa[x] & ((1 << h) - 1)];
            x = tau[((beta[x] >> l) | 1) << l];
        }
        
        if (j != beta[y])
        {
            int l = lam[alfa[y] & ((1 << h) - 1)];
            y = tau[((beta[y] >> l) | 1) << l];
        }
        
        // Find z
        int z = (pi[x] <= pi[y]) ? x : y;
        return z;
    }
    
    static List<int> SolveTestCase(int n, int[] values, int[,] queries)
    {
        List<int> results = new List<int>();
        
        int[] A = new int[n + 2];
        A[0] = int.MaxValue;  // A[0]
        int[] R = new int[n + 2];
        int[] B = new int[n + 2];
        
        int N = 1;
        int count = 0;
        int? oldx = null;
        
        for (int i = 1; i <= n; i++)
        {
            int x = values[i - 1];
            
            if (i > 1 && (oldx == null || x != oldx))
            {
                A[N] = count;
                R[N] = i;
                N++;
                count = 0;
            }
            
            B[i] = N;
            count++;
            oldx = x;
        }
        
        A[N] = count;
        R[N] = n + 1;
        
        Result result = Process(N, A);
        int[] pi = result.Pi;
        int[] beta = result.Beta;
        int[] alfa = result.Alfa;
        int[] tau = result.Tau;
        int[] lam = result.Lam;
        
        int queryCount = queries.GetLength(0);
        for (int q = 0; q < queryCount; q++)
        {
            int i = queries[q, 0];
            int j = queries[q, 1];
            int x = B[i];
            int y = B[j];
            
            int z;
            if (x == y)
            {
                z = j - i + 1;
            }
            else
            {
                if (x + 1 != y)
                {
                    z = A[Nca(x + 1, y - 1, beta, alfa, tau, lam, pi)];
                }
                else
                {
                    z = 0;
                }
                
                z = Math.Max(z, Math.Max(R[x] - i, A[y] - R[y] + j + 1));
            }
            
            results.Add(z);
        }
        
        return results;
    }
    
    static void Main(string[] args)
    {
        // Hard-coded test data
        List<TestCase> testCases = new List<TestCase>();
        testCases.Add(new TestCase(
            10,
            new int[] { -1, -1, 1, 1, 1, 1, 3, 10, 10, 10 },
            new int[,] { { 2, 3 }, { 1, 10 }, { 5, 10 } },
            new int[] { 1, 4, 3 }
        ));
        
        for (int idx = 0; idx < testCases.Count; idx++)
        {
            TestCase test = testCases[idx];
            int n = test.N;
            int[] values = test.Values;
            int[,] queries = test.Queries;
            int[] expected = test.Expected;
            
            Console.WriteLine($"Test Case {idx + 1}:");
            Console.WriteLine($"Size: {n}, Queries: {queries.GetLength(0)}");
            Console.Write("Values: ");
            foreach (int value in values)
            {
                Console.Write($"{value} ");
            }
            Console.WriteLine();
            
            List<int> results = SolveTestCase(n, values, queries);
            
            Console.WriteLine("Queries and Results:");
            for (int q_idx = 0; q_idx < queries.GetLength(0); q_idx++)
            {
                int query0 = queries[q_idx, 0];
                int query1 = queries[q_idx, 1];
                int result = results[q_idx];
                int exp = expected[q_idx];
                
                Console.WriteLine($"Query: {query0} {query1}");
                Console.WriteLine($"Result: {result} (Expected: {exp})");
                if (result != exp)
                {
                    Console.WriteLine("  WARNING: Result doesn't match expected output");
                }
            }
            
            Console.WriteLine();
        }
    }
}

class Node
{
    public int Child { get; set; } = 0;
    public int Sib { get; set; } = 0;
    public int Parent { get; set; } = 0;
}

class Result
{
    public int[] Pi { get; }
    public int[] Beta { get; }
    public int[] Alfa { get; }
    public int[] Tau { get; }
    public int[] Lam { get; }
    
    public Result(int[] pi, int[] beta, int[] alfa, int[] tau, int[] lam)
    {
        Pi = pi;
        Beta = beta;
        Alfa = alfa;
        Tau = tau;
        Lam = lam;
    }
}

class TestCase
{
    public int N { get; }
    public int[] Values { get; }
    public int[,] Queries { get; }
    public int[] Expected { get; }
    
    public TestCase(int n, int[] values, int[,] queries, int[] expected)
    {
        N = n;
        Values = values;
        Queries = queries;
        Expected = expected;
    }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10 
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)


Translation of: Java
Works with: COBOL
IDENTIFICATION DIVISION.
       PROGRAM-ID. JAVA-TO-COBOL.

       ENVIRONMENT DIVISION.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  VARS.
           05 N-IN PIC S9(9) COMP.
           05 Q-COUNT PIC S9(9) COMP.
           05 I PIC S9(9) COMP.
           05 J PIC S9(9) COMP.
           05 Q-IDX PIC S9(9) COMP.
           05 N-TOTAL PIC S9(9) COMP.
           05 COUNT-VAL PIC S9(9) COMP.
           05 OLDX PIC S9(9) COMP.
           05 X-VAL PIC S9(9) COMP.
           05 Y-VAL PIC S9(9) COMP.
           05 Z-VAL PIC S9(9) COMP.
           05 VAL1 PIC S9(9) COMP.
           05 VAL2 PIC S9(9) COMP.
           05 X-PLUS PIC S9(9) COMP.
           05 NCA-X PIC S9(9) COMP.
           05 NCA-Y PIC S9(9) COMP.
           05 NCA-RES PIC S9(9) COMP.
           05 IDX-N PIC S9(9) COMP.
           05 IDX-NCA PIC S9(9) COMP.
           05 IDX-X PIC S9(9) COMP.
           05 IDX-Y PIC S9(9) COMP.
           05 N PIC S9(9) COMP.
           05 T PIC S9(9) COMP.
           05 V PIC S9(9) COMP.
           05 U PIC S9(9) COMP.
           05 LOOP-DONE PIC S9(9) COMP.
           05 IDX-V PIC S9(9) COMP.
           05 IDX-T PIC S9(9) COMP.
           05 IDX-U PIC S9(9) COMP.
           05 P-VAR PIC S9(9) COMP.
           05 N-VAR PIC S9(9) COMP.
           05 TRAVERSAL-DONE PIC S9(9) COMP.
           05 S3-DONE PIC S9(9) COMP.
           05 S4-DONE PIC S9(9) COMP.
           05 HALF-N PIC S9(9) COMP.
           05 IDX-HALF PIC S9(9) COMP.
           05 IDX-P PIC S9(9) COMP.
           05 IDX-BETA-P PIC S9(9) COMP.
           05 H-VAR PIC S9(9) COMP.
           05 K-VAR PIC S9(9) COMP.
           05 L-VAR PIC S9(9) COMP.
           05 J-VAR PIC S9(9) COMP.
           05 TEMP-K PIC S9(9) COMP.
           05 MASK-VAL PIC S9(9) COMP.
           05 IDX-AND PIC S9(9) COMP.
           05 IDX-TAU PIC S9(9) COMP.
           05 ALFA-NODE PIC S9(9) COMP.
           05 CURR-NODE PIC S9(9) COMP.
           05 ALFA-DONE PIC S9(9) COMP.
           05 BACKTRACK-DONE PIC S9(9) COMP.
           05 IDX-CURR PIC S9(9) COMP.
           05 IDX-PARENT PIC S9(9) COMP.

       01  BIT-VARS.
           05 BIT-A PIC S9(9) COMP.
           05 BIT-B PIC S9(9) COMP.
           05 BIT-RES PIC S9(9) COMP.
           05 BIT-MUL PIC S9(9) COMP.
           05 TEMP-A PIC S9(9) COMP.
           05 TEMP-B PIC S9(9) COMP.
           05 REM-A PIC S9(9) COMP.
           05 REM-B PIC S9(9) COMP.
           05 BIT-IDX PIC S9(9) COMP.
           05 BIT-VAL PIC S9(9) COMP.
           05 BIT-SHIFT PIC S9(9) COMP.
           05 BIT-DIV PIC S9(9) COMP.

       01  ARRAYS.
           05 VALUES-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 QUERY-I OCCURS 10005 TIMES PIC S9(9) COMP.
           05 QUERY-J OCCURS 10005 TIMES PIC S9(9) COMP.
           05 EXPECTED-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 RESULTS-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 A-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 R-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 B-ARR OCCURS 10005 TIMES PIC S9(9) COMP.

       01  TREE-ARRAYS.
           05 PI-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 BETA-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 ALFA-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 TAU-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 LAM-ARR OCCURS 10005 TIMES PIC S9(9) COMP.
           05 NODES OCCURS 10005 TIMES.
              10 NODE-CHILD PIC S9(9) COMP VALUE 0.
              10 NODE-SIB PIC S9(9) COMP VALUE 0.
              10 NODE-PARENT PIC S9(9) COMP VALUE 0.

       01  DISP-VARS.
           05 DISP-NUM PIC -9(9).
           05 TEMP-STR-I PIC X(15).
           05 TEMP-STR-J PIC X(15).
           05 TEMP-STR-RES PIC X(15).
           05 TEMP-STR-EXP PIC X(15).

       PROCEDURE DIVISION.
       MAIN-PARA.
           MOVE 10 TO N-IN
           MOVE 3 TO Q-COUNT
           MOVE -1 TO VALUES-ARR(1)
           MOVE -1 TO VALUES-ARR(2)
           MOVE 1 TO VALUES-ARR(3)
           MOVE 1 TO VALUES-ARR(4)
           MOVE 1 TO VALUES-ARR(5)
           MOVE 1 TO VALUES-ARR(6)
           MOVE 3 TO VALUES-ARR(7)
           MOVE 10 TO VALUES-ARR(8)
           MOVE 10 TO VALUES-ARR(9)
           MOVE 10 TO VALUES-ARR(10)
           
           MOVE 2 TO QUERY-I(1)
           MOVE 3 TO QUERY-J(1)
           MOVE 1 TO EXPECTED-ARR(1)
           
           MOVE 1 TO QUERY-I(2)
           MOVE 10 TO QUERY-J(2)
           MOVE 4 TO EXPECTED-ARR(2)
           
           MOVE 5 TO QUERY-I(3)
           MOVE 10 TO QUERY-J(3)
           MOVE 3 TO EXPECTED-ARR(3)
           
           DISPLAY "Test Case 1:"
           DISPLAY "Size: " N-IN ", Queries: " Q-COUNT
           DISPLAY "Values: -1 -1 1 1 1 1 3 10 10 10"
           
           PERFORM SOLVE-TEST-CASE
           
           DISPLAY "Queries and Results:"
           PERFORM VARYING Q-IDX FROM 1 BY 1 UNTIL Q-IDX > Q-COUNT
               MOVE QUERY-I(Q-IDX) TO DISP-NUM
               MOVE DISP-NUM TO TEMP-STR-I
               MOVE QUERY-J(Q-IDX) TO DISP-NUM
               MOVE DISP-NUM TO TEMP-STR-J
               DISPLAY "Query: " FUNCTION TRIM(TEMP-STR-I) 
                       " " FUNCTION TRIM(TEMP-STR-J)
               
               MOVE RESULTS-ARR(Q-IDX) TO DISP-NUM
               MOVE DISP-NUM TO TEMP-STR-RES
               MOVE EXPECTED-ARR(Q-IDX) TO DISP-NUM
               MOVE DISP-NUM TO TEMP-STR-EXP
               DISPLAY "Result: " FUNCTION TRIM(TEMP-STR-RES) 
                       " (Expected: " FUNCTION TRIM(TEMP-STR-EXP) ")"
               
               IF RESULTS-ARR(Q-IDX) NOT = EXPECTED-ARR(Q-IDX)
                   DISPLAY "  WARNING: Result doesn't match expected"
               END-IF
           END-PERFORM
           
           STOP RUN.

       SOLVE-TEST-CASE.
           MOVE 2147483647 TO A-ARR(1)
           MOVE 1 TO N-TOTAL
           MOVE 0 TO COUNT-VAL
           MOVE -999999 TO OLDX
           
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > N-IN
               MOVE VALUES-ARR(I) TO X-VAL
               IF I > 1 AND X-VAL NOT = OLDX
                   COMPUTE IDX-N = N-TOTAL + 1
                   MOVE COUNT-VAL TO A-ARR(IDX-N)
                   MOVE I TO R-ARR(IDX-N)
                   ADD 1 TO N-TOTAL
                   MOVE 0 TO COUNT-VAL
               END-IF
               MOVE N-TOTAL TO B-ARR(I)
               ADD 1 TO COUNT-VAL
               MOVE X-VAL TO OLDX
           END-PERFORM
           
           COMPUTE IDX-N = N-TOTAL + 1
           MOVE COUNT-VAL TO A-ARR(IDX-N)
           COMPUTE R-ARR(IDX-N) = N-IN + 1
           
           MOVE N-TOTAL TO N
           PERFORM PROCESS-PARA
           
           PERFORM VARYING Q-IDX FROM 1 BY 1 UNTIL Q-IDX > Q-COUNT
               MOVE QUERY-I(Q-IDX) TO I
               MOVE QUERY-J(Q-IDX) TO J
               MOVE B-ARR(I) TO X-VAL
               MOVE B-ARR(J) TO Y-VAL
               
               IF X-VAL = Y-VAL
                   COMPUTE Z-VAL = J - I + 1
               ELSE
                   COMPUTE X-PLUS = X-VAL + 1
                   IF X-PLUS NOT = Y-VAL
                       COMPUTE NCA-X = X-VAL + 1
                       COMPUTE NCA-Y = Y-VAL - 1
                       PERFORM NCA-PARA
                       COMPUTE IDX-NCA = NCA-RES + 1
                       MOVE A-ARR(IDX-NCA) TO Z-VAL
                   ELSE
                       MOVE 0 TO Z-VAL
                   END-IF
                   
                   COMPUTE IDX-X = X-VAL + 1
                   COMPUTE VAL1 = R-ARR(IDX-X) - I
                   COMPUTE IDX-Y = Y-VAL + 1
                   COMPUTE VAL2 = A-ARR(IDX-Y) - R-ARR(IDX-Y) + J + 1
                   
                   IF VAL1 > Z-VAL
                       MOVE VAL1 TO Z-VAL
                   END-IF
                   IF VAL2 > Z-VAL
                       MOVE VAL2 TO Z-VAL
                   END-IF
               END-IF
               
               MOVE Z-VAL TO RESULTS-ARR(Q-IDX)
           END-PERFORM.

       PROCESS-PARA.
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > N + 1
               MOVE 0 TO NODE-CHILD(I)
               MOVE 0 TO NODE-SIB(I)
               MOVE 0 TO NODE-PARENT(I)
           END-PERFORM
           
           MOVE 0 TO T
           PERFORM VARYING V FROM N BY -1 UNTIL V <= 0
               MOVE 0 TO U
               MOVE 0 TO LOOP-DONE
               PERFORM UNTIL LOOP-DONE = 1
                   COMPUTE IDX-V = V + 1
                   COMPUTE IDX-T = T + 1
                   IF A-ARR(IDX-V) > A-ARR(IDX-T) OR 
                     (A-ARR(IDX-V) = A-ARR(IDX-T) AND V > T)
                       MOVE T TO U
                       MOVE NODE-PARENT(IDX-T) TO T
                   ELSE
                       MOVE 1 TO LOOP-DONE
                   END-IF
               END-PERFORM
               
               COMPUTE IDX-V = V + 1
               COMPUTE IDX-T = T + 1
               COMPUTE IDX-U = U + 1
               IF U NOT = 0
                   MOVE NODE-SIB(IDX-U) TO NODE-SIB(IDX-V)
                   MOVE 0 TO NODE-SIB(IDX-U)
                   MOVE V TO NODE-PARENT(IDX-U)
                   MOVE U TO NODE-CHILD(IDX-V)
               ELSE
                   MOVE NODE-CHILD(IDX-T) TO NODE-SIB(IDX-V)
               END-IF
               
               MOVE V TO NODE-CHILD(IDX-T)
               MOVE T TO NODE-PARENT(IDX-V)
               MOVE V TO T
           END-PERFORM
           
           MOVE NODE-CHILD(1) TO P-VAR
           MOVE 0 TO N-VAR
           MOVE -1 TO LAM-ARR(1)
           
           MOVE 0 TO TRAVERSAL-DONE
           PERFORM UNTIL TRAVERSAL-DONE = 1
               PERFORM TRAVERSAL-PARA
           END-PERFORM
           
           MOVE NODE-CHILD(1) TO P-VAR
           COMPUTE IDX-N = N-VAR + 1
           MOVE LAM-ARR(IDX-N) TO LAM-ARR(1)
           MOVE 0 TO PI-ARR(1)
           MOVE 0 TO BETA-ARR(1)
           MOVE 0 TO ALFA-ARR(1)
           
           IF P-VAR NOT = 0
               MOVE P-VAR TO ALFA-NODE
               PERFORM COMPUTE-ALFA
           END-IF.

       TRAVERSAL-PARA.
           MOVE 0 TO S3-DONE
           PERFORM UNTIL S3-DONE = 1
               ADD 1 TO N-VAR
               COMPUTE IDX-P = P-VAR + 1
               MOVE N-VAR TO PI-ARR(IDX-P)
               COMPUTE IDX-N = N-VAR + 1
               MOVE 0 TO TAU-ARR(IDX-N)
               COMPUTE HALF-N = N-VAR / 2
               COMPUTE IDX-HALF = HALF-N + 1
               COMPUTE LAM-ARR(IDX-N) = 1 + LAM-ARR(IDX-HALF)
               
               IF NODE-CHILD(IDX-P) NOT = 0
                   MOVE NODE-CHILD(IDX-P) TO P-VAR
               ELSE
                   MOVE N-VAR TO BETA-ARR(IDX-P)
                   MOVE 1 TO S3-DONE
               END-IF
           END-PERFORM
           
           MOVE 0 TO S4-DONE
           PERFORM UNTIL S4-DONE = 1
               COMPUTE IDX-P = P-VAR + 1
               COMPUTE IDX-BETA-P = BETA-ARR(IDX-P) + 1
               MOVE NODE-PARENT(IDX-P) TO TAU-ARR(IDX-BETA-P)
               
               IF NODE-SIB(IDX-P) NOT = 0
                   MOVE NODE-SIB(IDX-P) TO P-VAR
                   MOVE 1 TO S4-DONE
                   MOVE 0 TO TRAVERSAL-DONE
                   EXIT PARAGRAPH
               END-IF
               
               MOVE NODE-PARENT(IDX-P) TO P-VAR
               COMPUTE IDX-P = P-VAR + 1
               IF P-VAR NOT = 0
                   MOVE N-VAR TO BIT-A
                   COMPUTE BIT-B = 0 - PI-ARR(IDX-P)
                   PERFORM DO-BIT-AND
                   COMPUTE IDX-AND = BIT-RES + 1
                   MOVE LAM-ARR(IDX-AND) TO H-VAR
                   
                   COMPUTE BIT-VAL = N-VAR
                   COMPUTE BIT-SHIFT = H-VAR
                   PERFORM DO-BIT-SHIFT-RIGHT
                   MOVE BIT-RES TO BIT-A
                   MOVE 1 TO BIT-B
                   PERFORM DO-BIT-OR
                   MOVE BIT-RES TO BIT-VAL
                   COMPUTE BIT-SHIFT = H-VAR
                   PERFORM DO-BIT-SHIFT-LEFT
                   MOVE BIT-RES TO BETA-ARR(IDX-P)
               ELSE
                   MOVE 1 TO S4-DONE
                   MOVE 1 TO TRAVERSAL-DONE
                   EXIT PARAGRAPH
               END-IF
           END-PERFORM.

       COMPUTE-ALFA.
           MOVE ALFA-NODE TO CURR-NODE
           MOVE 0 TO ALFA-DONE
           PERFORM UNTIL ALFA-DONE = 1
               COMPUTE IDX-CURR = CURR-NODE + 1
               COMPUTE IDX-PARENT = NODE-PARENT(IDX-CURR) + 1
               
               MOVE BETA-ARR(IDX-CURR) TO BIT-A
               COMPUTE BIT-B = 0 - BETA-ARR(IDX-CURR)
               PERFORM DO-BIT-AND
               
               MOVE ALFA-ARR(IDX-PARENT) TO BIT-A
               MOVE BIT-RES TO BIT-B
               PERFORM DO-BIT-OR
               MOVE BIT-RES TO ALFA-ARR(IDX-CURR)
               
               IF NODE-CHILD(IDX-CURR) NOT = 0
                   MOVE NODE-CHILD(IDX-CURR) TO CURR-NODE
               ELSE
                   IF NODE-SIB(IDX-CURR) NOT = 0
                       MOVE NODE-SIB(IDX-CURR) TO CURR-NODE
                   ELSE
                       MOVE 0 TO BACKTRACK-DONE
                       PERFORM UNTIL BACKTRACK-DONE = 1
                           IF CURR-NODE = 0 OR 
                             NODE-SIB(IDX-CURR) NOT = 0
                               MOVE 1 TO BACKTRACK-DONE
                           ELSE
                               MOVE NODE-PARENT(IDX-CURR) TO CURR-NODE
                               COMPUTE IDX-CURR = CURR-NODE + 1
                           END-IF
                       END-PERFORM
                       
                       IF CURR-NODE = 0
                           MOVE 1 TO ALFA-DONE
                       ELSE
                           MOVE NODE-SIB(IDX-CURR) TO CURR-NODE
                       END-IF
                   END-IF
               END-IF
           END-PERFORM.

       NCA-PARA.
           COMPUTE IDX-X = NCA-X + 1
           COMPUTE IDX-Y = NCA-Y + 1
           
           IF BETA-ARR(IDX-X) <= BETA-ARR(IDX-Y)
               MOVE BETA-ARR(IDX-Y) TO BIT-A
               COMPUTE BIT-B = 0 - BETA-ARR(IDX-X)
               PERFORM DO-BIT-AND
               COMPUTE IDX-AND = BIT-RES + 1
               MOVE LAM-ARR(IDX-AND) TO H-VAR
           ELSE
               MOVE BETA-ARR(IDX-X) TO BIT-A
               COMPUTE BIT-B = 0 - BETA-ARR(IDX-Y)
               PERFORM DO-BIT-AND
               COMPUTE IDX-AND = BIT-RES + 1
               MOVE LAM-ARR(IDX-AND) TO H-VAR
           END-IF
           
           MOVE ALFA-ARR(IDX-X) TO BIT-A
           MOVE ALFA-ARR(IDX-Y) TO BIT-B
           PERFORM DO-BIT-AND
           MOVE BIT-RES TO TEMP-K
           
           COMPUTE BIT-VAL = 1
           COMPUTE BIT-SHIFT = H-VAR
           PERFORM DO-BIT-SHIFT-LEFT
           MOVE TEMP-K TO BIT-A
           COMPUTE BIT-B = 0 - BIT-RES
           PERFORM DO-BIT-AND
           MOVE BIT-RES TO K-VAR
           
           MOVE K-VAR TO BIT-A
           COMPUTE BIT-B = 0 - K-VAR
           PERFORM DO-BIT-AND
           COMPUTE IDX-AND = BIT-RES + 1
           MOVE LAM-ARR(IDX-AND) TO H-VAR
           
           COMPUTE BIT-VAL = BETA-ARR(IDX-X)
           COMPUTE BIT-SHIFT = H-VAR
           PERFORM DO-BIT-SHIFT-RIGHT
           MOVE BIT-RES TO BIT-A
           MOVE 1 TO BIT-B
           PERFORM DO-BIT-OR
           MOVE BIT-RES TO BIT-VAL
           COMPUTE BIT-SHIFT = H-VAR
           PERFORM DO-BIT-SHIFT-LEFT
           MOVE BIT-RES TO J-VAR
           
           IF J-VAR NOT = BETA-ARR(IDX-X)
               COMPUTE BIT-VAL = 1
               COMPUTE BIT-SHIFT = H-VAR
               PERFORM DO-BIT-SHIFT-LEFT
               COMPUTE MASK-VAL = BIT-RES - 1
               
               MOVE ALFA-ARR(IDX-X) TO BIT-A
               MOVE MASK-VAL TO BIT-B
               PERFORM DO-BIT-AND
               
               COMPUTE IDX-AND = BIT-RES + 1
               MOVE LAM-ARR(IDX-AND) TO L-VAR
               
               COMPUTE BIT-VAL = BETA-ARR(IDX-X)
               COMPUTE BIT-SHIFT = L-VAR
               PERFORM DO-BIT-SHIFT-RIGHT
               MOVE BIT-RES TO BIT-A
               MOVE 1 TO BIT-B
               PERFORM DO-BIT-OR
               MOVE BIT-RES TO BIT-VAL
               COMPUTE BIT-SHIFT = L-VAR
               PERFORM DO-BIT-SHIFT-LEFT
               COMPUTE IDX-TAU = BIT-RES + 1
               MOVE TAU-ARR(IDX-TAU) TO NCA-X
               COMPUTE IDX-X = NCA-X + 1
           END-IF
           
           IF J-VAR NOT = BETA-ARR(IDX-Y)
               COMPUTE BIT-VAL = 1
               COMPUTE BIT-SHIFT = H-VAR
               PERFORM DO-BIT-SHIFT-LEFT
               COMPUTE MASK-VAL = BIT-RES - 1
               
               MOVE ALFA-ARR(IDX-Y) TO BIT-A
               MOVE MASK-VAL TO BIT-B
               PERFORM DO-BIT-AND
               
               COMPUTE IDX-AND = BIT-RES + 1
               MOVE LAM-ARR(IDX-AND) TO L-VAR
               
               COMPUTE BIT-VAL = BETA-ARR(IDX-Y)
               COMPUTE BIT-SHIFT = L-VAR
               PERFORM DO-BIT-SHIFT-RIGHT
               MOVE BIT-RES TO BIT-A
               MOVE 1 TO BIT-B
               PERFORM DO-BIT-OR
               MOVE BIT-RES TO BIT-VAL
               COMPUTE BIT-SHIFT = L-VAR
               PERFORM DO-BIT-SHIFT-LEFT
               COMPUTE IDX-TAU = BIT-RES + 1
               MOVE TAU-ARR(IDX-TAU) TO NCA-Y
               COMPUTE IDX-Y = NCA-Y + 1
           END-IF
           
           IF PI-ARR(IDX-X) <= PI-ARR(IDX-Y)
               MOVE NCA-X TO NCA-RES
           ELSE
               MOVE NCA-Y TO NCA-RES
           END-IF.

       DO-BIT-AND.
           MOVE 0 TO BIT-RES
           MOVE 1 TO BIT-MUL
           MOVE BIT-A TO TEMP-A
           MOVE BIT-B TO TEMP-B
           PERFORM UNTIL TEMP-A >= 0
               COMPUTE TEMP-A = TEMP-A + 65536
           END-PERFORM
           PERFORM UNTIL TEMP-B >= 0
               COMPUTE TEMP-B = TEMP-B + 65536
           END-PERFORM
           PERFORM VARYING BIT-IDX FROM 1 BY 1 UNTIL BIT-IDX > 16
               DIVIDE TEMP-A BY 2 GIVING TEMP-A REMAINDER REM-A
               DIVIDE TEMP-B BY 2 GIVING TEMP-B REMAINDER REM-B
               IF REM-A = 1 AND REM-B = 1
                   COMPUTE BIT-RES = BIT-RES + BIT-MUL
               END-IF
               COMPUTE BIT-MUL = BIT-MUL * 2
           END-PERFORM.

       DO-BIT-OR.
           MOVE 0 TO BIT-RES
           MOVE 1 TO BIT-MUL
           MOVE BIT-A TO TEMP-A
           MOVE BIT-B TO TEMP-B
           PERFORM UNTIL TEMP-A >= 0
               COMPUTE TEMP-A = TEMP-A + 65536
           END-PERFORM
           PERFORM UNTIL TEMP-B >= 0
               COMPUTE TEMP-B = TEMP-B + 65536
           END-PERFORM
           PERFORM VARYING BIT-IDX FROM 1 BY 1 UNTIL BIT-IDX > 16
               DIVIDE TEMP-A BY 2 GIVING TEMP-A REMAINDER REM-A
               DIVIDE TEMP-B BY 2 GIVING TEMP-B REMAINDER REM-B
               IF REM-A = 1 OR REM-B = 1
                   COMPUTE BIT-RES = BIT-RES + BIT-MUL
               END-IF
               COMPUTE BIT-MUL = BIT-MUL * 2
           END-PERFORM.

       DO-BIT-SHIFT-LEFT.
           COMPUTE BIT-MUL = 2 ** BIT-SHIFT
           COMPUTE BIT-RES = BIT-VAL * BIT-MUL
           DIVIDE BIT-RES BY 65536 GIVING BIT-DIV REMAINDER BIT-RES.

       DO-BIT-SHIFT-RIGHT.
           COMPUTE BIT-MUL = 2 ** BIT-SHIFT
           DIVIDE BIT-VAL BY BIT-MUL GIVING BIT-RES.
Output:
Test Case 1:
Size: +000000010, Queries: +000000003
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 000000002 000000003
Result: 000000001 (Expected: 000000001)
Query: 000000001 000000010
Result: 000000004 (Expected: 000000004)
Query: 000000005 000000010
Result: 000000003 (Expected: 000000003)


Works with: Dart version 3.6.1
Translation of: Java
import 'dart:math';
import 'dart:collection';

class Node {
  int child = 0;
  int sib = 0;
  int parent = 0;
}

class Result {
  List<int> pi;
  List<int> beta;
  List<int> alfa;
  List<int> tau;
  List<int> lam;
  
  Result(this.pi, this.beta, this.alfa, this.tau, this.lam);
}

class TestCase {
  int n;
  List<int> values;
  List<List<int>> queries;
  List<int> expected;
  
  TestCase(this.n, this.values, this.queries, this.expected);
}

// Static variables for traversal
int _p = 0;
int _n = 0;

int getP() => _p;
int getN() => _n;

bool traversal(List<Node> nodes, int initialP, int initialN, List<int> pi, 
               List<int> beta, List<int> tau, List<int> lam) {
  _p = initialP;
  _n = initialN;
  
  // s3: Compute beta in the easy case
  while (true) {
    _n++;
    pi[_p] = _n;
    tau[_n] = 0;
    lam[_n] = 1 + lam[_n >> 1];
    
    if (nodes[_p].child != 0) {
      _p = nodes[_p].child;
      continue;
    }
    
    beta[_p] = _n;
    break;
  }
  
  // s4: Compute tau, bottom-up
  while (true) {
    tau[beta[_p]] = nodes[_p].parent;
    
    if (nodes[_p].sib != 0) {
      _p = nodes[_p].sib;
      return true;  // Go back to s3
    }
    
    _p = nodes[_p].parent;
    
    // Compute beta in the hard case
    if (_p != 0) {
      int h = lam[_n & -pi[_p]];
      beta[_p] = ((_n >> h) | 1) << h;
    } else {
      return false;  // Exit traversal
    }
  }
}

void compute_alfa(List<Node> nodes, int node, List<int> alfa, List<int> beta) {
  // s7: Compute alfa, top-down
  alfa[node] = alfa[nodes[node].parent] | (beta[node] & -beta[node]);
  
  if (nodes[node].child != 0) {
    compute_alfa(nodes, nodes[node].child, alfa, beta);
  }
  
  // s8: Continue traversal
  if (nodes[node].sib != 0) {
    compute_alfa(nodes, nodes[node].sib, alfa, beta);
  }
}

int nca(int x, int y, List<int> beta, List<int> alfa, 
        List<int> tau, List<int> lam, List<int> pi) {
  // Find common height
  int h;
  if (beta[x] <= beta[y]) {
    h = lam[beta[y] & -beta[x]];
  } else {
    h = lam[beta[x] & -beta[y]];
  }
  
  // Find true height
  int k = alfa[x] & alfa[y] & -(1 << h);
  h = lam[k & -k];
  
  // Find beta[z]
  int j = ((beta[x] >> h) | 1) << h;
  
  // Find x' and y'
  if (j != beta[x]) {
    int l = lam[alfa[x] & ((1 << h) - 1)];
    x = tau[((beta[x] >> l) | 1) << l];
  }
  
  if (j != beta[y]) {
    int l = lam[alfa[y] & ((1 << h) - 1)];
    y = tau[((beta[y] >> l) | 1) << l];
  }
  
  // Find z
  int z = (pi[x] <= pi[y]) ? x : y;
  return z;
}

Result process(int N, List<int> A) {
  List<int> pi = List<int>.filled(N + 1, 0);
  List<int> beta = List<int>.filled(N + 1, 0);
  List<int> alfa = List<int>.filled(N + 1, 0);
  List<int> tau = List<int>.filled(N + 1, 0);
  List<int> lam = List<int>.filled(N + 1, 0);
  List<Node> nodes = List<Node>.generate(N + 1, (_) => Node());
  
  // Make triply linked tree
  int t = 0;
  for (int v = N; v > 0; v--) {
    int u = 0;
    while (A[v] > A[t] || (A[v] == A[t] && v > t)) {
      u = t;
      t = nodes[t].parent;
    }
    
    if (u != 0) {
      nodes[v].sib = nodes[u].sib;
      nodes[u].sib = 0;
      nodes[u].parent = v;
      nodes[v].child = u;
    } else {
      nodes[v].sib = nodes[t].child;
    }
    
    nodes[t].child = v;
    nodes[v].parent = t;
    t = v;
  }
  
  // Begin first traversal
  int p = nodes[0].child;
  int n = 0;
  lam[0] = -1;
  
  while (traversal(nodes, p, n, pi, beta, tau, lam)) {
    // Continue traversal
    n = getN();
    p = getP();
  }
  
  // Begin second traversal
  p = nodes[0].child;
  lam[0] = lam[n];
  pi[0] = beta[0] = alfa[0] = 0;
  
  // Perform second traversal
  if (p != 0) {
    compute_alfa(nodes, p, alfa, beta);
  }
  
  return Result(pi, beta, alfa, tau, lam);
}

List<int> solve_test_case(int n, List<int> values, List<List<int>> queries) {
  List<int> results = [];
  
  List<int> A = List<int>.filled(n + 2, 0);
  A[0] = 1 << 30;  // A[0] = MAX_INT
  List<int> R = List<int>.filled(n + 2, 0);
  List<int> B = List<int>.filled(n + 2, 0);
  
  int N = 1;
  int count = 0;
  int? oldx;
  
  for (int i = 1; i <= n; i++) {
    int x = values[i - 1];
    
    if (i > 1 && (oldx == null || x != oldx)) {
      A[N] = count;
      R[N] = i;
      N++;
      count = 0;
    }
    
    B[i] = N;
    count++;
    oldx = x;
  }
  
  A[N] = count;
  R[N] = n + 1;
  
  Result result = process(N, A);
  List<int> pi = result.pi;
  List<int> beta = result.beta;
  List<int> alfa = result.alfa;
  List<int> tau = result.tau;
  List<int> lam = result.lam;
  
  for (List<int> query in queries) {
    int i = query[0];
    int j = query[1];
    int x = B[i];
    int y = B[j];
    
    int z;
    if (x == y) {
      z = j - i + 1;
    } else {
      if (x + 1 != y) {
        z = A[nca(x + 1, y - 1, beta, alfa, tau, lam, pi)];
      } else {
        z = 0;
      }
      
      z = max(z, max(R[x] - i, A[y] - R[y] + j + 1));
    }
    
    results.add(z);
  }
  
  return results;
}

void main() {
  // Hard-coded test data
  List<TestCase> testCases = [];
  testCases.add(TestCase(
    10,
    [-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
    [[2, 3], [1, 10], [5, 10]],
    [1, 4, 3]
  ));
  
  for (int idx = 0; idx < testCases.length; idx++) {
    TestCase test = testCases[idx];
    int n = test.n;
    List<int> values = test.values;
    List<List<int>> queries = test.queries;
    List<int> expected = test.expected;
    
    print("Test Case ${idx + 1}:");
    print("Size: $n, Queries: ${queries.length}");
    print("Values: ${values.join(' ')}");
    
    List<int> results = solve_test_case(n, values, queries);
    
    print("Queries and Results:");
    for (int q_idx = 0; q_idx < queries.length; q_idx++) {
      List<int> query = queries[q_idx];
      int result = results[q_idx];
      int exp = expected[q_idx];
      
      print("Query: ${query[0]} ${query[1]}");
      print("Result: $result (Expected: $exp)");
      if (result != exp) {
        print("  WARNING: Result doesn't match expected output");
      }
    }
    
    print("");
  }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)



Translation of: Python
Type Node
    child As Integer
    sib As Integer
    parent As Integer
End Type

Sub compute_alfa(node As Integer, nodes() As Node, beta() As Integer, alfa() As Integer)
    ' s7: Compute alfa, top-down
    alfa(node) = alfa(nodes(node).parent) Or (beta(node) And -beta(node))
    
    If nodes(node).child <> 0 Then compute_alfa(nodes(node).child, nodes(), beta(), alfa())
    
    ' s8: Continue traversal
    If nodes(node).sib <> 0 Then compute_alfa(nodes(node).sib, nodes(), beta(), alfa())
End Sub

Sub process(N As Integer, A() As Integer, pi() As Integer, beta() As Integer, alfa() As Integer, tau() As Integer, lam() As Integer)
    Dim As Node nodes(0 To 100)
    
    ' Make triply linked tree
    Dim As Integer t = 0
    For v As Integer = N To 1 Step -1
        Dim As Integer u = 0
        While A(v) > A(t) Or (A(v) = A(t) And v > t)
            u = t
            t = nodes(t).parent
        Wend
        
        If u <> 0 Then
            nodes(v).sib = nodes(u).sib
            nodes(u).sib = 0
            nodes(u).parent = v
            nodes(v).child = u
        Else
            nodes(v).sib = nodes(t).child
        End If
        
        nodes(t).child = v
        nodes(v).parent = t
        t = v
    Next
    
    ' Begin first traversal
    Dim As Integer p = nodes(0).child
    Dim As Integer m = 0
    lam(0) = -1
    
    Do
        ' s3: Compute beta in the easy case
        Do
            m += 1
            pi(p) = m
            tau(m) = 0
            lam(m) = 1 + lam(m Shr 1)
            If nodes(p).child <> 0 Then
                p = nodes(p).child
            Else
                beta(p) = m
                Exit Do
            End If
        Loop
        
        ' s4: Compute tau, bottom-up
        Do
            tau(beta(p)) = nodes(p).parent
            
            If nodes(p).sib <> 0 Then
                p = nodes(p).sib
                Exit Do
            End If
            
            p = nodes(p).parent
            
            ' Compute beta in the hard case
            If p <> 0 Then
                Dim h As Integer = lam(m And -pi(p))
                beta(p) = ((m Shr h) Or 1) Shl h
            Else
                Exit Do, Do
            End If
        Loop
    Loop While p <> 0
    
    ' Begin second traversal
    p = nodes(0).child
    lam(0) = lam(m)
    pi(0) = 0 : beta(0) = 0 : alfa(0) = 0
    
    ' Perform second traversal
    If p <> 0 Then compute_alfa(p, nodes(), beta(), alfa())
End Sub

Function nca(x As Integer, y As Integer, beta() As Integer, alfa() As Integer, tau() As Integer, lam() As Integer, pi() As Integer) As Integer
    Dim As Integer h, k, j, l
    
    ' Find common height
    If beta(x) <= beta(y) Then
        h = lam(beta(y) And -beta(x))
    Else
        h = lam(beta(x) And -beta(y))
    End If
    
    ' Find true height
    k = alfa(x) And alfa(y) And -(1 Shl h)
    If k = 0 Then
        h = 0
    Else
        h = lam(k And -k)
    End If
    
    ' Find beta[z]
    j = ((beta(x) Shr h) Or 1) Shl h
    
    ' Find x' and y'
    If j <> beta(x) Then
        l = lam(alfa(x) And ((1 Shl h) - 1))
        x = tau(((beta(x) Shr l) Or 1) Shl l)
    End If
    
    If j <> beta(y) Then
        l = lam(alfa(y) And ((1 Shl h) - 1))
        y = tau(((beta(y) Shr l) Or 1) Shl l)
    End If
    
    ' Find z
    Return Iif(pi(x) <= pi(y), x, y)
End Function

Sub solve_test_case(m As Integer, values() As Integer, queries() As Integer, num_queries As Integer, expected() As Integer)
    Dim As Integer A(100), R(100), B(100)
    Dim As Integer pi(100), beta(100), alfa(100), tau(100), lam(100)
    
    A(0) = 2147483647
    Dim As Integer N = 1, cnt = 0, oldx = 0
    
    For i As Integer = 1 To m
        Dim As Integer x = values(i)
        If i > 1 And x <> oldx Then
            A(N) = cnt
            R(N) = i
            N += 1
            cnt = 0
        End If
        B(i) = N
        cnt += 1
        oldx = x
    Next
    A(N) = cnt
    R(N) = m + 1
    
    process(N, A(), pi(), beta(), alfa(), tau(), lam())
    
    Print "Queries and Results:"
    For q As Integer = 1 To num_queries
        Dim As Integer i1 = queries((q - 1) * 2 + 1)
        Dim As Integer j1 = queries((q - 1) * 2 + 2)
        Dim As Integer x1 = B(i1)
        Dim As Integer y1 = B(j1)
        Dim As Integer z
        
        If x1 = y1 Then
            z = j1 - i1 + 1
        Else
            If x1 + 1 <> y1 Then
                z = A(nca(x1 + 1, y1 - 1, beta(), alfa(), tau(), lam(), pi()))
            Else
                z = 0
            End If
            If (R(x1) - i1) > z Then z = R(x1) - i1
            If (A(y1) - R(y1) + j1 + 1) > z Then z = A(y1) - R(y1) + j1 + 1
        End If
        
        Print "Query: "; i1; " "; j1
        Print "Result: "; z; " (Expected: "; expected(q); ")"
        If z <> expected(q) Then Print "  WARNING: Result doesn't match expected output"
    Next
    Print
End Sub

' Hard-coded test data
Dim As Integer values(1 To 10) = {-1, -1, 1, 1, 1, 1, 3, 10, 10, 10}
Dim As Integer queries(1 To 6) = {2, 3, 1, 10, 5, 10}
Dim As Integer expected(1 To 3) = {1, 4, 3}

Print "Test Case 1:"
Print "Size: 10, Queries: 3"
Print "Values: ";
For i As Integer = 1 To 10
    Print values(i);  ' " ";
Next
Print

solve_test_case(10, values(), queries(), 3, expected())

Sleep
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1-1 1 1 1 1 3 10 10 10
Queries and Results:
Query:  2  3
Result:  1 (Expected:  1)
Query:  1  10
Result:  4 (Expected:  4)
Query:  5  10
Result:  3 (Expected:  3)
Works with: Go version 1.10.2
Translation of: Java
package main

import (
	"fmt"
	"math"
)

type Node struct {
	Child  int
	Sib    int
	Parent int
}

type Result struct {
	Pi   []int
	Beta []int
	Alfa []int
	Tau  []int
	Lam  []int
}

// Process function replicates the main logic
func process(N int, A []int) Result {
	pi := make([]int, N+1)
	beta := make([]int, N+1)
	alfa := make([]int, N+1)
	tau := make([]int, N+1)
	lam := make([]int, N+1)
	nodes := make([]Node, N+1)

	// Make triply linked tree
	t := 0
	for v := N; v > 0; v-- {
		u := 0
		for A[v] > A[t] || (A[v] == A[t] && v > t) {
			u = t
			t = nodes[t].Parent
		}

		if u != 0 {
			nodes[v].Sib = nodes[u].Sib
			nodes[u].Sib = 0
			nodes[u].Parent = v
			nodes[v].Child = u
		} else {
			nodes[v].Sib = nodes[t].Child
		}

		nodes[t].Child = v
		nodes[v].Parent = t
		t = v
	}

	// First traversal
	p := nodes[0].Child
	n := 0
	lam[0] = -1

	for traversal(nodes, p, n, pi, beta, tau, lam) {
		n = getN()
		p = getP()
	}

	// Second traversal
	p = nodes[0].Child
	lam[0] = lam[n]
	pi[0] = 0
	beta[0] = 0
	alfa[0] = 0

	if p != 0 {
		computeAlfa(nodes, p, alfa, beta)
	}

	return Result{Pi: pi, Beta: beta, Alfa: alfa, Tau: tau, Lam: lam}
}

// Static variables to simulate nonlocal variables
var p, n int

func getP() int {
	return p
}

func getN() int {
	return n
}

func traversal(nodes []Node, initialP, initialN int, pi, beta, tau, lam []int) bool {
	p = initialP
	n = initialN

	for {
		n++
		pi[p] = n
		tau[n] = 0
		lam[n] = 1 + lam[n>>1]

		if nodes[p].Child != 0 {
			p = nodes[p].Child
			continue
		}

		beta[p] = n
		break
	}

	for {
		tau[beta[p]] = nodes[p].Parent

		if nodes[p].Sib != 0 {
			p = nodes[p].Sib
			return true
		}

		p = nodes[p].Parent

		if p != 0 {
			h := lam[n&-pi[p]]
			beta[p] = ((n >> h) | 1) << h
		} else {
			return false
		}
	}
}

func computeAlfa(nodes []Node, node int, alfa, beta []int) {
	alfa[node] = alfa[nodes[node].Parent] | (beta[node] & -beta[node])

	if nodes[node].Child != 0 {
		computeAlfa(nodes, nodes[node].Child, alfa, beta)
	}

	if nodes[node].Sib != 0 {
		computeAlfa(nodes, nodes[node].Sib, alfa, beta)
	}
}

func nca(x, y int, beta, alfa, tau, lam, pi []int) int {
	var h int
	if beta[x] <= beta[y] {
		h = lam[beta[y]&-beta[x]]
	} else {
		h = lam[beta[x]&-beta[y]]
	}

	k := alfa[x] & alfa[y] & -(1 << h)
	h = lam[k&-k]

	j := ((beta[x] >> h) | 1) << h

	if j != beta[x] {
		l := lam[alfa[x]&((1<<h)-1)]
		x = tau[((beta[x]>>l)|1)<<l]
	}

	if j != beta[y] {
		l := lam[alfa[y]&((1<<h)-1)]
		y = tau[((beta[y]>>l)|1)<<l]
	}

	if pi[x] <= pi[y] {
		return x
	}
	return y
}

func solveTestCase(n int, values []int, queries [][]int) []int {
	results := []int{}

	A := make([]int, n+2)
	A[0] = math.MaxInt32
	R := make([]int, n+2)
	B := make([]int, n+2)

	N := 1
	count := 0
	var oldx *int

	for i := 1; i <= n; i++ {
		x := values[i-1]

		if i > 1 && (oldx == nil || x != *oldx) {
			A[N] = count
			R[N] = i
			N++
			count = 0
		}

		B[i] = N
		count++
		oldx = &x
	}

	A[N] = count
	R[N] = n + 1

	result := process(N, A)
	pi := result.Pi
	beta := result.Beta
	alfa := result.Alfa
	tau := result.Tau
	lam := result.Lam

	for _, query := range queries {
		i, j := query[0], query[1]
		x, y := B[i], B[j]

		var z int
		if x == y {
			z = j - i + 1
		} else {
			if x+1 != y {
				z = A[nca(x+1, y-1, beta, alfa, tau, lam, pi)]
			} else {
				z = 0
			}

			z = max(z, max(R[x]-i, A[y]-R[y]+j+1))
		}

		results = append(results, z)
	}

	return results
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	testCases := []struct {
		n        int
		values   []int
		queries  [][]int
		expected []int
	}{
		{
			n:      10,
			values: []int{-1, -1, 1, 1, 1, 1, 3, 10, 10, 10},
			queries: [][]int{
				{2, 3}, {1, 10}, {5, 10},
			},
			expected: []int{1, 4, 3},
		},
	}

	for idx, testCase := range testCases {
		fmt.Printf("Test Case %d:\n", idx+1)
		results := solveTestCase(testCase.n, testCase.values, testCase.queries)
		fmt.Println("Results:", results)
	}
}
Output:
Test Case 1:
Results: [1 4 3]


Works with: Java version LTS version 17
Translation of: Python
import java.util.*;

class Main {
    static Result process(int N, int[] A) {
        int[] pi = new int[N + 1];
        int[] beta = new int[N + 1];
        int[] alfa = new int[N + 1];
        int[] tau = new int[N + 1];
        int[] lam = new int[N + 1];
        Node[] nodes = new Node[N + 1];
        for (int i = 0; i <= N; i++) {
            nodes[i] = new Node();
        }
        
        // Make triply linked tree
        int t = 0;
        for (int v = N; v > 0; v--) {
            int u = 0;
            while (A[v] > A[t] || (A[v] == A[t] && v > t)) {
                u = t;
                t = nodes[t].parent;
            }
            
            if (u != 0) {
                nodes[v].sib = nodes[u].sib;
                nodes[u].sib = 0;
                nodes[u].parent = v;
                nodes[v].child = u;
            } else {
                nodes[v].sib = nodes[t].child;
            }
            
            nodes[t].child = v;
            nodes[v].parent = t;
            t = v;
        }
        
        // Begin first traversal
        int p = nodes[0].child;
        int n = 0;
        lam[0] = -1;
        
        while (traversal(nodes, p, n, pi, beta, tau, lam)) {
            // Continue traversal
            n = getN();
            p = getP();
        }
        
        // Begin second traversal
        p = nodes[0].child;
        lam[0] = lam[n];
        pi[0] = beta[0] = alfa[0] = 0;
        
        // Perform second traversal
        if (p != 0) {
            compute_alfa(nodes, p, alfa, beta);
        }
        
        return new Result(pi, beta, alfa, tau, lam);
    }
    
    // These static variables are used to simulate the nonlocal variables in Python
    private static int p;
    private static int n;
    
    private static int getP() {
        return p;
    }
    
    private static int getN() {
        return n;
    }
    
    static boolean traversal(Node[] nodes, int initialP, int initialN, int[] pi, int[] beta, int[] tau, int[] lam) {
        p = initialP;
        n = initialN;
        
        // s3: Compute beta in the easy case
        while (true) {
            n++;
            pi[p] = n;
            tau[n] = 0;
            lam[n] = 1 + lam[n >> 1];
            
            if (nodes[p].child != 0) {
                p = nodes[p].child;
                continue;
            }
            
            beta[p] = n;
            break;
        }
        
        // s4: Compute tau, bottom-up
        while (true) {
            tau[beta[p]] = nodes[p].parent;
            
            if (nodes[p].sib != 0) {
                p = nodes[p].sib;
                return true;  // Go back to s3
            }
            
            p = nodes[p].parent;
            
            // Compute beta in the hard case
            if (p != 0) {
                int h = lam[n & -pi[p]];
                beta[p] = ((n >> h) | 1) << h;
            } else {
                return false;  // Exit traversal
            }
        }
    }
    
    static void compute_alfa(Node[] nodes, int node, int[] alfa, int[] beta) {
        // s7: Compute alfa, top-down
        alfa[node] = alfa[nodes[node].parent] | (beta[node] & -beta[node]);
        
        if (nodes[node].child != 0) {
            compute_alfa(nodes, nodes[node].child, alfa, beta);
        }
        
        // s8: Continue traversal
        if (nodes[node].sib != 0) {
            compute_alfa(nodes, nodes[node].sib, alfa, beta);
        }
    }
    
    static int nca(int x, int y, int[] beta, int[] alfa, int[] tau, int[] lam, int[] pi) {
        // Find common height
        int h;
        if (beta[x] <= beta[y]) {
            h = lam[beta[y] & -beta[x]];
        } else {
            h = lam[beta[x] & -beta[y]];
        }
        
        // Find true height
        int k = alfa[x] & alfa[y] & -(1 << h);
        h = lam[k & -k];
        
        // Find beta[z]
        int j = ((beta[x] >> h) | 1) << h;
        
        // Find x' and y'
        if (j != beta[x]) {
            int l = lam[alfa[x] & ((1 << h) - 1)];
            x = tau[((beta[x] >> l) | 1) << l];
        }
        
        if (j != beta[y]) {
            int l = lam[alfa[y] & ((1 << h) - 1)];
            y = tau[((beta[y] >> l) | 1) << l];
        }
        
        // Find z
        int z = (pi[x] <= pi[y]) ? x : y;
        return z;
    }
    
    static List<Integer> solve_test_case(int n, int[] values, int[][] queries) {
        List<Integer> results = new ArrayList<>();
        
        int[] A = new int[n + 2];
        A[0] = Integer.MAX_VALUE;  // A[0]
        int[] R = new int[n + 2];
        int[] B = new int[n + 2];
        
        int N = 1;
        int count = 0;
        Integer oldx = null;
        
        for (int i = 1; i <= n; i++) {
            int x = values[i - 1];
            
            if (i > 1 && (oldx == null || x != oldx)) {
                A[N] = count;
                R[N] = i;
                N++;
                count = 0;
            }
            
            B[i] = N;
            count++;
            oldx = x;
        }
        
        A[N] = count;
        R[N] = n + 1;
        
        Result result = process(N, A);
        int[] pi = result.pi;
        int[] beta = result.beta;
        int[] alfa = result.alfa;
        int[] tau = result.tau;
        int[] lam = result.lam;
        
        for (int[] query : queries) {
            int i = query[0];
            int j = query[1];
            int x = B[i];
            int y = B[j];
            
            int z;
            if (x == y) {
                z = j - i + 1;
            } else {
                if (x + 1 != y) {
                    z = A[nca(x + 1, y - 1, beta, alfa, tau, lam, pi)];
                } else {
                    z = 0;
                }
                
                z = Math.max(z, Math.max(R[x] - i, A[y] - R[y] + j + 1));
            }
            
            results.add(z);
        }
        
        return results;
    }
    
    public static void main(String[] args) {
        // Hard-coded test data
        List<TestCase> testCases = new ArrayList<>();
        testCases.add(new TestCase(
            10,
            new int[]{-1, -1, 1, 1, 1, 1, 3, 10, 10, 10},
            new int[][]{{2, 3}, {1, 10}, {5, 10}},
            new int[]{1, 4, 3}
        ));
        
        for (int idx = 0; idx < testCases.size(); idx++) {
            TestCase test = testCases.get(idx);
            int n = test.n;
            int[] values = test.values;
            int[][] queries = test.queries;
            int[] expected = test.expected;
            
            System.out.println("Test Case " + (idx + 1) + ":");
            System.out.println("Size: " + n + ", Queries: " + queries.length);
            System.out.print("Values: ");
            for (int value : values) {
                System.out.print(value + " ");
            }
            System.out.println();
            
            List<Integer> results = solve_test_case(n, values, queries);
            
            System.out.println("Queries and Results:");
            for (int q_idx = 0; q_idx < queries.length; q_idx++) {
                int[] query = queries[q_idx];
                int result = results.get(q_idx);
                int exp = expected[q_idx];
                
                System.out.println("Query: " + query[0] + " " + query[1]);
                System.out.println("Result: " + result + " (Expected: " + exp + ")");
                if (result != exp) {
                    System.out.println("  WARNING: Result doesn't match expected output");
                }
            }
            
            System.out.println();
        }
    }
    
    static class TestCase {
        int n;
        int[] values;
        int[][] queries;
        int[] expected;
        
        public TestCase(int n, int[] values, int[][] queries, int[] expected) {
            this.n = n;
            this.values = values;
            this.queries = queries;
            this.expected = expected;
        }
    }
}

class Node {
    int child = 0;
    int sib = 0;
    int parent = 0;
}

class Result {
    int[] pi;
    int[] beta;
    int[] alfa;
    int[] tau;
    int[] lam;
    
    public Result(int[] pi, int[] beta, int[] alfa, int[] tau, int[] lam) {
        this.pi = pi;
        this.beta = beta;
        this.alfa = alfa;
        this.tau = tau;
        this.lam = lam;
    }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10 
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)


Works with: NodeJS 16.14.2
Translation of: Java
class Node {
  constructor() {
    this.child = 0;
    this.sib = 0;
    this.parent = 0;
  }
}

class Result {
  constructor(pi, beta, alfa, tau, lam) {
    this.pi = pi;
    this.beta = beta;
    this.alfa = alfa;
    this.tau = tau;
    this.lam = lam;
  }
}

function process(N, A) {
  const pi = Array(N + 1).fill(0);
  const beta = Array(N + 1).fill(0);
  const alfa = Array(N + 1).fill(0);
  const tau = Array(N + 1).fill(0);
  const lam = Array(N + 1).fill(0);
  const nodes = Array.from({ length: N + 1 }, () => new Node());

  let t = 0;

  // Build triply linked tree
  for (let v = N; v > 0; v--) {
    let u = 0;
    while (A[v] > A[t] || (A[v] === A[t] && v > t)) {
      u = t;
      t = nodes[t].parent;
    }

    if (u !== 0) {
      nodes[v].sib = nodes[u].sib;
      nodes[u].sib = 0;
      nodes[u].parent = v;
      nodes[v].child = u;
    } else {
      nodes[v].sib = nodes[t].child;
    }

    nodes[t].child = v;
    nodes[v].parent = t;
    t = v;
  }

  // First traversal
  let p = nodes[0].child;
  let n = 0;
  lam[0] = -1;

  while (traversal(nodes, p, n, pi, beta, tau, lam)) {
    n = getN();
    p = getP();
  }

  // Second traversal
  p = nodes[0].child;
  lam[0] = lam[n];
  pi[0] = beta[0] = alfa[0] = 0;

  if (p !== 0) {
    computeAlfa(nodes, p, alfa, beta);
  }

  return new Result(pi, beta, alfa, tau, lam);
}

// Static variables to simulate nonlocal variables
let p, n;

function getP() {
  return p;
}

function getN() {
  return n;
}

function traversal(nodes, initialP, initialN, pi, beta, tau, lam) {
  p = initialP;
  n = initialN;

  while (true) {
    n++;
    pi[p] = n;
    tau[n] = 0;
    lam[n] = 1 + lam[n >> 1];

    if (nodes[p].child !== 0) {
      p = nodes[p].child;
      continue;
    }

    beta[p] = n;
    break;
  }

  while (true) {
    tau[beta[p]] = nodes[p].parent;

    if (nodes[p].sib !== 0) {
      p = nodes[p].sib;
      return true;
    }

    p = nodes[p].parent;

    if (p !== 0) {
      const h = lam[n & -pi[p]];
      beta[p] = ((n >> h) | 1) << h;
    } else {
      return false;
    }
  }
}

function computeAlfa(nodes, node, alfa, beta) {
  alfa[node] = alfa[nodes[node].parent] | (beta[node] & -beta[node]);

  if (nodes[node].child !== 0) {
    computeAlfa(nodes, nodes[node].child, alfa, beta);
  }

  if (nodes[node].sib !== 0) {
    computeAlfa(nodes, nodes[node].sib, alfa, beta);
  }
}

function nca(x, y, beta, alfa, tau, lam, pi) {
  let h;
  if (beta[x] <= beta[y]) {
    h = lam[beta[y] & -beta[x]];
  } else {
    h = lam[beta[x] & -beta[y]];
  }

  const k = alfa[x] & alfa[y] & -(1 << h);
  h = lam[k & -k];

  const j = ((beta[x] >> h) | 1) << h;

  if (j !== beta[x]) {
    const l = lam[alfa[x] & ((1 << h) - 1)];
    x = tau[((beta[x] >> l) | 1) << l];
  }

  if (j !== beta[y]) {
    const l = lam[alfa[y] & ((1 << h) - 1)];
    y = tau[((beta[y] >> l) | 1) << l];
  }

  return pi[x] <= pi[y] ? x : y;
}

function solveTestCase(n, values, queries) {
  const results = [];
  const A = Array(n + 2).fill(0);
  const R = Array(n + 2).fill(0);
  const B = Array(n + 2).fill(0);

  A[0] = Number.MAX_SAFE_INTEGER;
  let N = 1;
  let count = 0;
  let oldx = null;

  for (let i = 1; i <= n; i++) {
    const x = values[i - 1];

    if (i > 1 && (oldx === null || x !== oldx)) {
      A[N] = count;
      R[N] = i;
      N++;
      count = 0;
    }

    B[i] = N;
    count++;
    oldx = x;
  }

  A[N] = count;
  R[N] = n + 1;

  const result = process(N, A);
  const { pi, beta, alfa, tau, lam } = result;

  for (const query of queries) {
    const [i, j] = query;
    const x = B[i];
    const y = B[j];

    let z;
    if (x === y) {
      z = j - i + 1;
    } else {
      if (x + 1 !== y) {
        z = A[nca(x + 1, y - 1, beta, alfa, tau, lam, pi)];
      } else {
        z = 0;
      }

      z = Math.max(z, Math.max(R[x] - i, A[y] - R[y] + j + 1));
    }

    results.push(z);
  }

  return results;
}

// Example usage
const testCases = [
  {
    n: 10,
    values: [-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
    queries: [
      [2, 3],
      [1, 10],
      [5, 10],
    ],
    expected: [1, 4, 3],
  },
];

for (const testCase of testCases) {
  const { n, values, queries, expected } = testCase;
  const results = solveTestCase(n, values, queries);
  console.log("Results:", results);
  console.log("Expected:", expected);
}
Output:
Results: [ 1, 4, 3 ]
Expected: [ 1, 4, 3 ]
Translation of: Python
""" rosettacode.org/wiki/Schieber-Vishkin_algorithm """


""" Node structure for a triply linked tree. """
mutable struct Node{T <: Integer}
    child::T
    sib::T
    parent::T
end
Node() = Node{Int}(0, 0, 0)

""" Process the input array `a` of size `n` into a triply linked tree
    and return the vectors pi_, beta, alfa, tau, and lam.
"""
function process(n::Integer, a::Vector)::Tuple
    pi_ = zeros(Int, n + 1) # pi is a builtin constant in Julia
    beta = zeros(Int, n + 1)
    alfa = zeros(Int, n + 1)
    tau = zeros(Int, n + 1)
    lam = zeros(Int, n + 1)
    nodes = [Node() for _ in 1:n+1] # Create n+1 default Node objects

    # Make triply linked tree
    t = 0
    for v in n:-1:1
        u = 0
        while a[v+1] > a[t+1] || (a[v+1] == a[t+1] && v > t)
            u = t
            t = nodes[t+1].parent
        end

        if u != 0
            nodes[v+1].sib = nodes[u+1].sib
            nodes[u+1].sib = 0
            nodes[u+1].parent = v
            nodes[v+1].child = u
        else
            nodes[v+1].sib = nodes[t+1].child
        end

        nodes[t+1].child = v
        nodes[v+1].parent = t
        t = v
    end

    # Begin first traversal
    p = nodes[begin].child
    n_count = 0
    lam[begin] = -1

    """ First traversal function """
    function traversal()
        while true
            # s3: Compute beta in the easy case
            n_count += 1
            pi_[p+1] = n_count
            tau[n_count+1] = 0
            lam[n_count+1] = 1 + lam[(n_count >> 1) + 1]

            if nodes[p+1].child != 0
                p = nodes[p+1].child
                continue # Go back to the beginning of the `while true` loop (s3)
            end

            beta[p+1] = n_count
            break
        end

        # s4: Compute tau, bottom-up
        while true
            tau[beta[p+1]] = nodes[p+1].parent

            if nodes[p+1].sib != 0
                p = nodes[p+1].sib
                return true 
            end

            p = nodes[p+1].parent

            # Compute beta in the hard case
            if p != 0
                h = lam[(n_count & (-pi_[p+1])) + 1] # Adjust index for lam access
                beta[p+1] = ((n_count >> h) | 1) << h
            else
                return false # Exit traversal
            end
        end
    end
     # Perform first traversal
    while traversal(); end

    # Begin second traversal
    p = nodes[begin].child
    lam[begin] = lam[n_count+1] 
    pi_[begin] = 0 
    beta[begin] = 0
    alfa[begin] = 0

    """ Recursive function for second traversal """
    function compute_alfa(node)
        # s7: Compute alfa, top-down
        alfa[node+1] = alfa[nodes[node+1].parent + 1] | (beta[node+1] & (-beta[node+1]))

        if nodes[node+1].child != 0
            compute_alfa(nodes[node+1].child)
        end

        # s8: Continue traversal
        if nodes[node+1].sib != 0
            compute_alfa(nodes[node+1].sib)
        end
    end

    # Perform second (recursive) traversal if needed
    p != 0 && compute_alfa(p)
    return pi_, beta, alfa, tau, lam
end

""" Compute the nearest common ancestor (NCA) of two nodes x and y """
function nca(
    x::Int,
    y::Int,
    beta::Vector{Int},
    alfa::Vector{Int},
    tau::Vector{Int},
    lam::Vector{Int},
    pi_::Vector{Int},
)
    # Find common height
    h = beta[x+1] <= beta[y+1] ? lam[(beta[y+1] & (-beta[x+1] + 1)) + 1] : lam[(beta[x+1] & (-beta[y+1]) + 1) + 1]

    # Find true height
    k = alfa[x+1] & alfa[y+1] & (~(1 << h) + 1) # `~X + 1` is `-X`
    h = lam[(k & (-k)) + 1]

    # Find beta[z]
    j = ((beta[x+1] >> h) | 1) << h

    # Find x' and y'
    if j != beta[x+1]
        l = lam[(alfa[x+1] & ((1 << h) - 1)) + 1]
        x = tau[(((beta[x+1] >> l) | 1) << l) + 1]
    end

    if j != beta[y+1]
        l = lam[(alfa[y+1] & ((1 << h) - 1)) + 1]
        y = tau[(((beta[y+1] >> l) | 1) << l) + 1]
    end

    # Find z
    return pi_[x+1] <= pi_[y+1] ? x : y
end

""" Solve a test case using Schieber-Vishkin given values and queries, 
    running the queries in parallel using threads.
"""
function schiebervishkin(
	n::Int,
	values::Vector{Int32},
	queries::Vector{Tuple{Int, Int}},
)
	results = zeros(Int32, length(queries))

	a = Int[typemax(Int32)]
	r = zeros(Int, n + 2)
	b = zeros(Int, n + 2)

	big_n = 1
	count = 0
	oldx = nothing

	for i in 1:n
		x = values[i]

		if i > 1 && x != oldx
			push!(a, count)
			r[big_n+1] = i
			big_n += 1
			count = 0
		end

		b[i] = big_n
		count += 1
		oldx = x # Store the value directly
	end

	push!(a, count)
	r[big_n+1] = n + 1

	(pi_, beta, alfa, tau, lam) = process(big_n, a)

	Threads.@threads for t in eachindex(queries)
		i, j = queries[t]
		x, y = b[i], b[j]

		z = 0
		if x == y
			z = (j - i + 1)
		else
			if x + 1 != y
				z = a[nca(x + 1, y - 1, beta, alfa, tau, lam, pi_) + 1]
			end
			z = max(z, r[x+1] - i, a[y+1] - (r[y+1] - j - 1))
		end
		results[t] = z
	end

	return results
end

function main()
    # Hard-coded test data
    test_cases = [
        (
            10, # n
            Int32[-1, -1, 1, 1, 1, 1, 3, 10, 10, 10], # values (Int32)
            [(2, 3), (1, 10), (5, 10)], # queries (Tuple of Int)
            Int32[1, 4, 3] # expected (Int32)
        )
    ]

    for (idx, (n, values, queries, expected)) in enumerate(test_cases)
        println("Test Case $(idx):")
        println("Size: $(n), Queries: $(length(queries))")
        println("Values: ", join(map(string, values), " "))

        results = schiebervishkin(n, values, queries)

        println("Queries and Results:")
        for q_idx in eachindex(queries)
            i, j = queries[q_idx]
            result = results[q_idx]
            exp = expected[q_idx]

            println("Query: $(i) $(j)")
            println("Result: $(result) (Expected: $(exp))")
            if result != exp
                println("  WARNING: Result doesn't match expected output")
            end
        end

        println()
    end
end

main()
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)
Works with: Kotlin version 1.3.31
Translation of: Java
import java.util.*

data class Node(
    var child: Int = 0,
    var sib: Int = 0,
    var parent: Int = 0
)

data class Result(
    val pi: IntArray,
    val beta: IntArray,
    val alfa: IntArray,
    val tau: IntArray,
    val lam: IntArray
)

data class TestCase(
    val n: Int,
    val values: IntArray,
    val queries: Array<IntArray>,
    val expected: IntArray
)

class CodeKt{
    // These variables are used to simulate the nonlocal variables in Python
    private var p = 0
    private var n = 0

    private fun getP(): Int = p
    private fun getN(): Int = n

    fun process(N: Int, A: IntArray): Result {
        val pi = IntArray(N + 1)
        val beta = IntArray(N + 1)
        val alfa = IntArray(N + 1)
        val tau = IntArray(N + 1)
        val lam = IntArray(N + 1)
        val nodes = Array(N + 1) { Node() }
        
        // Make triply linked tree
        var t = 0
        for (v in N downTo 1) {
            var u = 0
            while (A[v] > A[t] || (A[v] == A[t] && v > t)) {
                u = t
                t = nodes[t].parent
            }
            
            if (u != 0) {
                nodes[v].sib = nodes[u].sib
                nodes[u].sib = 0
                nodes[u].parent = v
                nodes[v].child = u
            } else {
                nodes[v].sib = nodes[t].child
            }
            
            nodes[t].child = v
            nodes[v].parent = t
            t = v
        }
        
        // Begin first traversal
        var p = nodes[0].child
        var n = 0
        lam[0] = -1
        
        while (traversal(nodes, p, n, pi, beta, tau, lam)) {
            // Continue traversal
            n = getN()
            p = getP()
        }
        
        // Begin second traversal
        p = nodes[0].child
        lam[0] = lam[n]
        pi[0] = 0
        beta[0] = 0
        alfa[0] = 0
        
        // Perform second traversal
        if (p != 0) {
            computeAlfa(nodes, p, alfa, beta)
        }
        
        return Result(pi, beta, alfa, tau, lam)
    }
    
    fun traversal(nodes: Array<Node>, initialP: Int, initialN: Int, pi: IntArray, beta: IntArray, tau: IntArray, lam: IntArray): Boolean {
        p = initialP
        n = initialN
        
        // s3: Compute beta in the easy case
        while (true) {
            n++
            pi[p] = n
            tau[n] = 0
            lam[n] = 1 + lam[n shr 1]
            
            if (nodes[p].child != 0) {
                p = nodes[p].child
                continue
            }
            
            beta[p] = n
            break
        }
        
        // s4: Compute tau, bottom-up
        while (true) {
            tau[beta[p]] = nodes[p].parent
            
            if (nodes[p].sib != 0) {
                p = nodes[p].sib
                return true  // Go back to s3
            }
            
            p = nodes[p].parent
            
            // Compute beta in the hard case
            if (p != 0) {
                val h = lam[n and -pi[p]]
                beta[p] = ((n shr h) or 1) shl h
            } else {
                return false  // Exit traversal
            }
        }
    }
    
    fun computeAlfa(nodes: Array<Node>, node: Int, alfa: IntArray, beta: IntArray) {
        // s7: Compute alfa, top-down
        alfa[node] = alfa[nodes[node].parent] or (beta[node] and -beta[node])
        
        if (nodes[node].child != 0) {
            computeAlfa(nodes, nodes[node].child, alfa, beta)
        }
        
        // s8: Continue traversal
        if (nodes[node].sib != 0) {
            computeAlfa(nodes, nodes[node].sib, alfa, beta)
        }
    }
    
    fun nca(x: Int, y: Int, beta: IntArray, alfa: IntArray, tau: IntArray, lam: IntArray, pi: IntArray): Int {
        // Find common height
        val h = if (beta[x] <= beta[y]) {
            lam[beta[y] and -beta[x]]
        } else {
            lam[beta[x] and -beta[y]]
        }
        
        // Find true height
        val k = alfa[x] and alfa[y] and -(1 shl h)
        val trueH = lam[k and -k]
        
        // Find beta[z]
        val j = ((beta[x] shr trueH) or 1) shl trueH
        
        // Find x' and y'
        var newX = x
        var newY = y
        
        if (j != beta[x]) {
            val l = lam[alfa[x] and ((1 shl trueH) - 1)]
            newX = tau[((beta[x] shr l) or 1) shl l]
        }
        
        if (j != beta[y]) {
            val l = lam[alfa[y] and ((1 shl trueH) - 1)]
            newY = tau[((beta[y] shr l) or 1) shl l]
        }
        
        // Find z
        return if (pi[newX] <= pi[newY]) newX else newY
    }
    
    fun solveTestCase(n: Int, values: IntArray, queries: Array<IntArray>): List<Int> {
        val results = mutableListOf<Int>()
        
        val A = IntArray(n + 2)
        A[0] = Int.MAX_VALUE  // A[0]
        val R = IntArray(n + 2)
        val B = IntArray(n + 2)
        
        var N = 1
        var count = 0
        var oldX: Int? = null
        
        for (i in 1..n) {
            val x = values[i - 1]
            
            if (i > 1 && (oldX == null || x != oldX)) {
                A[N] = count
                R[N] = i
                N++
                count = 0
            }
            
            B[i] = N
            count++
            oldX = x
        }
        
        A[N] = count
        R[N] = n + 1
        
        val result = process(N, A)
        val pi = result.pi
        val beta = result.beta
        val alfa = result.alfa
        val tau = result.tau
        val lam = result.lam
        
        for (query in queries) {
            val i = query[0]
            val j = query[1]
            val x = B[i]
            val y = B[j]
            
            val z = if (x == y) {
                j - i + 1
            } else {
                val commonAncestorValue = if (x + 1 != y) {
                    A[nca(x + 1, y - 1, beta, alfa, tau, lam, pi)]
                } else {
                    0
                }
                
                maxOf(commonAncestorValue, maxOf(R[x] - i, A[y] - R[y] + j + 1))
            }
            
            results.add(z)
        }
        
        return results
    }
    
    @JvmStatic
    fun main(args: Array<String>) {
        // Hard-coded test data
        val testCases = listOf(
            TestCase(
                10,
                intArrayOf(-1, -1, 1, 1, 1, 1, 3, 10, 10, 10),
                arrayOf(
                    intArrayOf(2, 3),
                    intArrayOf(1, 10),
                    intArrayOf(5, 10)
                ),
                intArrayOf(1, 4, 3)
            )
        )
        
        for ((idx, test) in testCases.withIndex()) {
            val n = test.n
            val values = test.values
            val queries = test.queries
            val expected = test.expected
            
            println("Test Case ${idx + 1}:")
            println("Size: $n, Queries: ${queries.size}")
            print("Values: ")
            values.forEach { print("$it ") }
            println()
            
            val results = solveTestCase(n, values, queries)
            
            println("Queries and Results:")
            for (qIdx in queries.indices) {
                val query = queries[qIdx]
                val result = results[qIdx]
                val exp = expected[qIdx]
                
                println("Query: ${query[0]} ${query[1]}")
                println("Result: $result (Expected: $exp)")
                if (result != exp) {
                    println("  WARNING: Result doesn't match expected output")
                }
            }
            
            println()
        }
    }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10 
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)
Translation of: Pluto
-- WARNING: horrible mashup of 0|1|2-based indexing, and logical|bitwise|math operations (tee-hee!)
enum CHILD,SIB,PARENT
--enum PIE,BETA,ALFA,TAU,LAM -- (not actually used anymore)

function computeAlfa(integer node, sequence alfa, beta, nodes)

    node += 1
    alfa[node] = alfa[nodes[node][PARENT]+1] || (beta[node] && -beta[node])

    if nodes[node][CHILD]!=0 then
        alfa = computeAlfa(nodes[node][CHILD],alfa,beta,nodes)
    end if

    if nodes[node][SIB]!=0 then
        alfa = computeAlfa(nodes[node][SIB],alfa,beta,nodes)
    end if
    return alfa
end function

function process(integer N, sequence A)

    sequence pie = repeat(0,N+1),
            beta = repeat(0,N+1),
            alfa = repeat(0,N+1),
             tau = repeat(0,N+1),
             lam = repeat(0,N+1),
           nodes = repeat({0,0,0},N+1)

    -- Make triply linked tree.
    integer t = 1
    for v=N+1 to 2 by -1 do
        integer u = 0
        while A[v]>A[t] or (A[v]==A[t] and v>t) do
            u = t
            t = nodes[t][PARENT]+1
        end while
        if u!=0 then
            nodes[v][SIB] = nodes[u][SIB]
            nodes[u][SIB] = 0
            nodes[u][PARENT] = v-1
            nodes[v][CHILD] = u-1
        else
            nodes[v][SIB] = nodes[t][CHILD]
        end if
        nodes[t][CHILD] = v-1
        nodes[v][PARENT] = t-1
        t = v
    end for

    -- First traversal.
    integer p = nodes[1][CHILD]+1, n = 0
    lam[1] = -1

    bool done = false
    while not done do
        -- Compute beta in the easy case.
        while true do
            n += 1
            pie[p] = n
            tau[n+1] = 0
            lam[n+1] = 1 + lam[(n>>1)+1]

            if nodes[p][CHILD]=0 then
                beta[p] = n
                exit
            end if

            p = nodes[p][CHILD]+1
        end while

        -- Compute tau, bottom-up.
        while true do
            tau[beta[p]] = nodes[p][PARENT]

            if nodes[p][SIB]!=0 then
                p = nodes[p][SIB]+1
                exit
            end if

            p = nodes[p][PARENT]+1
            if p=1 then
                done = true
                exit
            end if
            -- Compute beta in the hard case.
            integer h = lam[(n&&-pie[p])+1]
            beta[p] = ((n>>h)||1) << h
        end while
    end while

    -- Second traversal.
    p = nodes[1][CHILD]
    lam[1] = lam[n]
    alfa[1] = 0
    beta[1] = 0
    pie[1] = 0

    if p!=0 then 
        alfa = computeAlfa(p,alfa,beta,nodes)
    end if
    return {pie, beta, alfa, tau, lam}
end function

function nca(integer x, y, sequence r)

    sequence {pie, beta, alfa, tau, lam} = r
    x += 1
    y += 1
    -- Find common height.
    integer h = iff(beta[x]<=beta[y]?lam[(beta[y]&&-beta[x])+1]
                                    :lam[(beta[x]&&-beta[y])+1])

    -- Find true height.
    integer k = alfa[x]&&alfa[y]&&-(1<<h)
    h = lam[(k&&-k)+1]

    -- Find beta[z].
    integer j = ((beta[x]>>h)||1) << h

    -- Find x' and y'.
    integer l
    if j != beta[x] then
        l = lam[(alfa[x]&&((1<<h)-1))+1]
        x = tau[(((beta[x]>>l)||1)<<l)+1]
    end if

    if j != beta[y] then
        l = lam[(alfa[y]&&((1<<h)-1))+1]
        y = tau[(((beta[y]>>l)||1)<<l)+1]
    end if

    -- Find z.
    integer z = iff(pie[x]<=pie[y] ? x : y)
    return z
end function

function solve_test_case(integer n, sequence v, queries)

    sequence res = {},
               A = {power(2,30)},
               R = repeat(0,n),
               B = repeat(0,n)

    integer N = 1,
        count = 0,
         oldx = -1

    for i,x in v do
        if i>1 and x!=oldx then
            A &= count
            R[N] = i
            N += 1
            count = 0
        end if
        B[i] = N
        count += 1
        oldx = x
    end for

    A &= count
    R[N] = n+1

    sequence r = process(N,A)

    for t in queries do
        integer {i,j} = t,
                    x = B[i],
                    y = B[j],
                    z = j-i+1 -- (x==y case)
        if x!=y then
            z = iff(x+1!=y?A[nca(x+1, y-1, r)]:0)
            z = max(z,max(R[x]-i,A[y+1]-R[y]+j+1))
        end if
        res &= z
    end for
    return res
end function

constant tests = {
    {{-1, -1, 1, 1, 1, 1, 3, 10, 10, 10},
     {{{2,3},1},{{1,10},4},{{5,10},3}}}
}

for idx, t in tests do
    sequence {v,q} = t
    integer n = length(v)

    printf(1,"Test Case %d:\n",idx)
    printf(1,"Size: %d, Queries: %d\n",{n,length(q)})
    printf(1,"Values: %s\n",{join(v,fmt:="%d")})

    sequence results = solve_test_case(n,v,vslice(q,1))

    printf(1,"Queries and Results:\n")
    for qdx,qe in q do
        integer {{i,j},e} = qe,
                   result = results[qdx]
        printf(1,"Query: %d %d\n",{i,j})
        printf(1,"Result: %d (Expected: %d)\n",{result,e})
        if result!=e then
            printf(1,"  WARNING: Result doesn't match expected output\n")
        end if
    end for
    printf(1,"\n")
end for
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)
Translation of: Python

Although Pluto arrays use 1-based indexing by default, they can in fact be indexed from any integer.

I've therefore used 0-based indexing for the working arrays (and noted where this has been done) to make the translation from Python easier.

local class Node
    function __construct()
        self.child = 0
        self.sib   = 0
        self.parnt = 0 -- NOTE: parent is a reserved word
    end
end

local class Result
    -- NOTE: 0-based indexing used for all 5 arrays.
    function __construct(pi, beta, alfa, tau, lam)
        self.pi   = pi
        self.beta = beta
        self.alfa = alfa
        self.tau  = tau
        self.lam  = lam
    end
end

-- NOTE: A is a 0-based array.
local function process(N, A)
    -- NOTE: 0-based indexing used for all 6 of the following arrays.
    local pi    = {}
    local beta  = {}
    local alfa  = {}
    local tau   = {}
    local lam   = {}
    local nodes = {}
    for i = 0, N do
        pi[i]    = 0
        beta[i]  = 0
        alfa[i]  = 0
        tau[i]   = 0
        lam[i]   = 0
        nodes[i] = new Node()
    end

    -- Make triply linked tree.
    local t = 0
    for v = N, 1, -1 do
        local u = 0
        while A[v] > A[t] or (A[v] == A[t] and v > t) do
            u = t
            t = nodes[t].parnt
        end
        if u != 0 then
            nodes[v].sib = nodes[u].sib
            nodes[u].sib = 0
            nodes[u].parnt = v
            nodes[v].child = u
        else
            nodes[v].sib = nodes[t].child
        end
        nodes[t].child = v
        nodes[v].parnt = t
        t = v
    end

    -- Begin first traversal.
    local p = nodes[0].child
    local n = 0
    lam[0] = -1

    local function traversal()
        -- s3: Compute beta in the easy case.
        while true do
            ++n
            pi[p] = n
            tau[n] = 0
            lam[n] = 1 + lam[n >> 1]

            if nodes[p].child != 0 then
                p = nodes[p].child
                continue
            end

            beta[p] = n
            break
        end

        -- s4: Compute tau, bottom-up.
        while true do
            tau[beta[p]] = nodes[p].parnt

            if nodes[p].sib != 0 then
                p = nodes[p].sib
                return true  -- go back to s3
            end

            p = nodes[p].parnt

            -- Compute beta in the hard case.
            if p != 0 then
                local h = lam[n & -pi[p]]
                beta[p] = ((n >> h) | 1) << h
            else
                return false  -- exit traversal
            end
        end
    end

    -- Perform first traversal.
    while traversal() do ; end

    -- Begin second traversal.
    p = nodes[0].child
    lam[0]  = lam[n]
    alfa[0] = 0
    beta[0] = 0
    pi[0]   = 0

    local function computeAlfa(node)
        -- s7: Compute alfa, top-down.
        alfa[node] = alfa[nodes[node].parnt] | (beta[node] & -beta[node])

        if nodes[node].child != 0 then
            computeAlfa(nodes[node].child)
        end

        -- s8: Continue traversal.
        if nodes[node].sib != 0 then
            computeAlfa(nodes[node].sib)
        end
    end

    -- Perform second traversal.
    if p != 0 then computeAlfa(p) end

    return new Result(pi, beta, alfa, tau, lam)
end

-- NOTE: All 5 incoming arrays are 0-based.
local function nca(x, y, beta, alfa, tau, lam, pi)
    -- Find common height.
    local h
    if beta[x] <= beta[y] then
        h = lam[beta[y] & -beta[x]]
    else
        h = lam[beta[x] & -beta[y]]
    end

    -- Find true height.
    local k = alfa[x] & alfa[y] & -(1 << h)
    h = lam[k & -k]

    -- Find beta[z].
    local j = ((beta[x] >> h) | 1) << h

    -- Find x' and y'.
    local l
    if j != beta[x] then
        l = lam[alfa[x] & ((1 << h) - 1)]
        x = tau[((beta[x] >> l) | 1) << l]
    end

    if j != beta[y] then
        l = lam[alfa[y] & ((1 << h) - 1)]
        y = tau[((beta[y] >> l) | 1) << l]
    end

    -- Find z.
    local z = pi[x] <= pi[y] ? x : y
    return z
end

local function solve_test_case(n, values, queries)
    local results = {}

    -- NOTE: A, R and B are 0-based arrays.
    local A = {}
    A[0] = math.maxinteger
    local R = {}
    local B = {}
    for i = 0, n + 1  do
        R[i] = 0
        B[i] = 0
    end

    local N = 1
    local count = 0
    local oldx = nil

    for i = 1, n do
        local x = values[i] -- values is 1-based

        if i > 1 and x != oldx then
            A:insert(count)
            R[N] = i
            N += 1
            count = 0
        end

        B[i] = N
        count += 1
        oldx = x
    end

    A:insert(count)
    R[N] = n + 1

    local r = process(N, A)

    for queries as t do  -- t is 1-based
        local i = t[1]
        local j = t[2]
        local x = B[i]
        local y = B[j]
        local z

        if x == y then
            z = j - i + 1
        else
            if x + 1 != y then
                z = A[nca(x + 1, y - 1, r.beta, r.alfa, r.tau, r.lam, r.pi)]
            else
                z = 0
            end
            z = math.max(z, math.max(R[x] - i, A[y] - R[y] + j + 1))
        end
        results:insert(z)
    end
    return results
end

-- Hard-coded test data.
local testCases = {
    {
        n        = 10,
        values   = {-1, -1, 1, 1, 1, 1, 3, 10, 10, 10},
        queries  = {{2, 3}, {1, 10}, {5, 10}},
        expected = {1, 4, 3}
    }
}

for idx, test in testCases do
    local n = test["n"]
    local values = test["values"]
    local queries = test["queries"]
    local expected = test["expected"]

    print($"Test Case {idx}:")
    print($"Size: {n}, Queries: {#queries}")
    print($"Values: {values:concat(" ")}")

    local results = solve_test_case(n, values, queries)

    print("Queries and Results:")
    for qIdx = 1, #queries do
        local q = queries[qIdx]
        local i = q[1]
        local j = q[2]
        local result = results[qIdx]
        local exp = expected[qIdx]
        print($"Query: {i} {j}")
        print($"Result: {result} (Expected: {exp})")
        if result != exp then
            print("  WARNING: Result doesn't match expected output")
        end
    end
    print()
end
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)
Translation of: FreeBASIC
Structure Node
  child.i
  sib.i
  parent.i
EndStructure

Procedure compute_alfa(node, Array nodes.Node(1), Array beta.i(1), Array alfa.i(1))
  alfa(node) = alfa(nodes(node)\parent) | (beta(node) & -beta(node))
  If nodes(node)\child <> 0
    compute_alfa(nodes(node)\child, nodes(), beta(), alfa())
  EndIf
  If nodes(node)\sib <> 0
    compute_alfa(nodes(node)\sib, nodes(), beta(), alfa())
  EndIf
EndProcedure

Procedure process(N, Array A.i(1), Array pi.i(1), Array beta.i(1), Array alfa.i(1), Array tau.i(1), Array lam.i(1))
  Dim nodes.Node(100)
  t = 0
  For v = N To 1 Step -1
    u = 0
    While A(v) > A(t) Or (A(v) = A(t) And v > t)
      u = t
      t = nodes(t)\parent
    Wend
    If u <> 0
      nodes(v)\sib = nodes(u)\sib
      nodes(u)\sib = 0
      nodes(u)\parent = v
      nodes(v)\child = u
    Else
      nodes(v)\sib = nodes(t)\child
    EndIf
    nodes(t)\child = v
    nodes(v)\parent = t
    t = v
  Next
  
  p = nodes(0)\child
  m = 0
  lam(0) = -1
  
  Repeat
    Repeat
      m + 1
      pi(p) = m
      tau(m) = 0
      lam(m) = 1 + lam(m >> 1)
      If nodes(p)\child <> 0
        p = nodes(p)\child
      Else
        beta(p) = m
        Break
      EndIf
    ForEver
    
    Repeat
      tau(beta(p)) = nodes(p)\parent
      If nodes(p)\sib <> 0
        p = nodes(p)\sib
        Break
      EndIf
      p = nodes(p)\parent
      If p <> 0
        h = lam(m & -pi(p))
        beta(p) = ((m >> h) | 1) << h
      Else
        Break 2
      EndIf
    ForEver
  Until p = 0
  
  p = nodes(0)\child
  lam(0) = lam(m)
  pi(0) = 0 : beta(0) = 0 : alfa(0) = 0
  
  If p <> 0
    compute_alfa(p, nodes(), beta(), alfa())
  EndIf
EndProcedure

Procedure.i nca(x, y, Array beta.i(1), Array alfa.i(1), Array tau.i(1), Array lam.i(1), Array pi.i(1))
  If beta(x) <= beta(y)
    h = lam(beta(y) & -beta(x))
  Else
    h = lam(beta(x) & -beta(y))
  EndIf
  
  k = alfa(x) & alfa(y) & -(1 << h)
  If k = 0
    h = 0
  Else
    h = lam(k & -k)
  EndIf
  
  j = ((beta(x) >> h) | 1) << h
  
  If j <> beta(x)
    l = lam(alfa(x) & ((1 << h) - 1))
    x = tau(((beta(x) >> l) | 1) << l)
  EndIf
  If j <> beta(y)
    l = lam(alfa(y) & ((1 << h) - 1))
    y = tau(((beta(y) >> l) | 1) << l)
  EndIf
  
  If pi(x) <= pi(y)
    ProcedureReturn x
  Else
    ProcedureReturn y
  EndIf
EndProcedure

Procedure solve_test_case(m, Array values.i(1), Array queries.i(1), num_queries, Array expected.i(1))
  Dim A.i(100)
  Dim R.i(100)
  Dim B.i(100)
  Dim pi.i(100)
  Dim beta.i(100)
  Dim alfa.i(100)
  Dim tau.i(100)
  Dim lam.i(100)
  
  A(0) = 2147483647
  N = 1 : cnt = 0 : oldx = 0
  
  For i = 1 To m
    x = values(i)
    If i > 1 And x <> oldx
      A(N) = cnt
      R(N) = i
      N + 1
      cnt = 0
    EndIf
    B(i) = N
    cnt + 1
    oldx = x
  Next
  A(N) = cnt
  R(N) = m + 1
  
  process(N, A(), pi(), beta(), alfa(), tau(), lam())
  
  PrintN("Queries and Results:")
  For q = 1 To num_queries
    i1 = queries((q - 1) * 2 + 1)
    j1 = queries((q - 1) * 2 + 2)
    x1 = B(i1)
    y1 = B(j1)
    z = 0
    
    If x1 = y1
      z = j1 - i1 + 1
    Else
      If x1 + 1 <> y1
        z = A(nca(x1 + 1, y1 - 1, beta(), alfa(), tau(), lam(), pi()))
      Else
        z = 0
      EndIf
      If (R(x1) - i1) > z : z = R(x1) - i1 : EndIf
      If (A(y1) - R(y1) + j1 + 1) > z : z = A(y1) - R(y1) + j1 + 1 : EndIf
    EndIf
    
    PrintN("Query: " + Str(i1) + " " + Str(j1))
    PrintN("Result: " + Str(z) + " (Expected: " + Str(expected(q)) + ")")
    If z <> expected(q)
      PrintN("  WARNING: Result doesn't match expected output")
    EndIf
  Next
  PrintN("")
EndProcedure

OpenConsole()
Dim values.i(10)
Dim queries.i(6)
Dim expected.i(3)

values(1) = -1 : values(2) = -1 : values(3) = 1 : values(4) = 1 : values(5) = 1
values(6) = 1 : values(7) = 3 : values(8) = 10 : values(9) = 10 : values(10) = 10

queries(1) = 2 : queries(2) = 3
queries(3) = 1 : queries(4) = 10
queries(5) = 5 : queries(6) = 10

expected(1) = 1 : expected(2) = 4 : expected(3) = 3

PrintN("Test Case 1:")
PrintN("Size: 10, Queries: 3")
Print("Values:")
For i = 1 To 10
  Print(" " + Str(values(i)))
Next
PrintN("")

solve_test_case(10, values(), queries(), 3, expected())
PrintN(#CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
Output:
Similar to FreeBASIC entry.
Works with: Python version 3.12
import sys
from typing import List, Tuple

class Node:
    def __init__(self):
        self.child = 0
        self.sib = 0
        self.parent = 0

def process(N: int, A: List[int]) -> Tuple[List[int], List[int], List[int], List[int], List[int]]:
    pi = [0] * (N + 1)
    beta = [0] * (N + 1)
    alfa = [0] * (N + 1)
    tau = [0] * (N + 1)
    lam = [0] * (N + 1)
    nodes = [Node() for _ in range(N + 1)]
    
    # Make triply linked tree
    t = 0
    for v in range(N, 0, -1):
        u = 0
        while A[v] > A[t] or (A[v] == A[t] and v > t):
            u = t
            t = nodes[t].parent
        
        if u:
            nodes[v].sib = nodes[u].sib
            nodes[u].sib = 0
            nodes[u].parent = v
            nodes[v].child = u
        else:
            nodes[v].sib = nodes[t].child
        
        nodes[t].child = v
        nodes[v].parent = t
        t = v
    
    # Begin first traversal
    p = nodes[0].child
    n = 0
    lam[0] = -1
    
    def traversal():
        nonlocal p, n
        
        # s3: Compute beta in the easy case
        while True:
            n += 1
            pi[p] = n
            tau[n] = 0
            lam[n] = 1 + lam[n >> 1]
            
            if nodes[p].child:
                p = nodes[p].child
                continue
            
            beta[p] = n
            break
        
        # s4: Compute tau, bottom-up
        while True:
            tau[beta[p]] = nodes[p].parent
            
            if nodes[p].sib:
                p = nodes[p].sib
                return True  # Go back to s3
            
            p = nodes[p].parent
            
            # Compute beta in the hard case
            if p:
                h = lam[n & -pi[p]]
                beta[p] = ((n >> h) | 1) << h
            else:
                return False  # Exit traversal
    
    # Perform first traversal
    while traversal():
        pass
    
    # Begin second traversal
    p = nodes[0].child
    lam[0] = lam[n]
    pi[0] = beta[0] = alfa[0] = 0
    
    def compute_alfa(node):
        nonlocal p
        
        # s7: Compute alfa, top-down
        alfa[node] = alfa[nodes[node].parent] | (beta[node] & -beta[node])
        
        if nodes[node].child:
            compute_alfa(nodes[node].child)
        
        # s8: Continue traversal
        if nodes[node].sib:
            compute_alfa(nodes[node].sib)
    
    # Perform second traversal
    if p:
        compute_alfa(p)
    
    return pi, beta, alfa, tau, lam

def nca(x: int, y: int, beta: List[int], alfa: List[int], tau: List[int], lam: List[int], pi: List[int]) -> int:
    # Find common height
    if beta[x] <= beta[y]:
        h = lam[beta[y] & -beta[x]]
    else:
        h = lam[beta[x] & -beta[y]]
    
    # Find true height
    k = alfa[x] & alfa[y] & -(1 << h)
    h = lam[k & -k]
    
    # Find beta[z]
    j = ((beta[x] >> h) | 1) << h
    
    # Find x' and y'
    if j != beta[x]:
        l = lam[alfa[x] & ((1 << h) - 1)]
        x = tau[((beta[x] >> l) | 1) << l]
    
    if j != beta[y]:
        l = lam[alfa[y] & ((1 << h) - 1)]
        y = tau[((beta[y] >> l) | 1) << l]
    
    # Find z
    z = x if pi[x] <= pi[y] else y
    return z

def solve_test_case(n: int, values: List[int], queries: List[Tuple[int, int]]) -> List[int]:
    results = []
    
    A = [sys.maxsize]  # A[0]
    R = [0] * (n + 2)
    B = [0] * (n + 2)
    
    N = 1
    count = 0
    oldx = None
    
    for i in range(1, n + 1):
        x = values[i - 1]
        
        if i > 1 and x != oldx:
            A.append(count)
            R[N] = i
            N += 1
            count = 0
        
        B[i] = N
        count += 1
        oldx = x
    
    A.append(count)
    R[N] = n + 1
    
    pi, beta, alfa, tau, lam = process(N, A)
    
    for i, j in queries:
        x, y = B[i], B[j]
        
        if x == y:
            z = j - i + 1
        else:
            if x + 1 != y:
                z = A[nca(x + 1, y - 1, beta, alfa, tau, lam, pi)]
            else:
                z = 0
            
            z = max(z, max(R[x] - i, A[y] - R[y] + j + 1))
        
        results.append(z)
    
    return results

def main():
    # Hard-coded test data
    test_cases = [
        {
            "n": 10,
            "values": [-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
            "queries": [(2, 3), (1, 10), (5, 10)],
            "expected": [1, 4, 3]
        }
    ]
    
    for idx, test in enumerate(test_cases):
        n = test["n"]
        values = test["values"]
        queries = test["queries"]
        expected = test["expected"]
        
        print(f"Test Case {idx + 1}:")
        print(f"Size: {n}, Queries: {len(queries)}")
        print(f"Values: {' '.join(map(str, values))}")
        
        results = solve_test_case(n, values, queries)
        
        print("Queries and Results:")
        for q_idx, ((i, j), result, exp) in enumerate(zip(queries, results, expected)):
            print(f"Query: {i} {j}")
            print(f"Result: {result} (Expected: {exp})")
            if result != exp:
                print("  WARNING: Result doesn't match expected output")
        
        print()

if __name__ == "__main__":
    main()
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)


R

Works with: R
Translation of: Julia
# Schieber-Vishkin Algorithm Implementation in R
# Based on rosettacode.org/wiki/Schieber-Vishkin_algorithm

# Node structure for a triply linked tree
create_node <- function() {
  list(child = 0, sib = 0, parent = 0)
}

# Process the input array `a` of size `n` into a triply linked tree
# and return the vectors pi_, beta, alfa, tau, and lam
process <- function(n, a) {
  pi_ <- integer(n + 1)
  beta <- integer(n + 1)
  alfa <- integer(n + 1)
  tau <- integer(n + 1)
  lam <- integer(n + 1)
  
  # Create n+1 default Node objects
  nodes <- vector("list", n + 1)
  for (i in 1:(n + 1)) {
    nodes[[i]] <- create_node()
  }
  
  # Make triply linked tree
  t <- 0
  for (v in n:1) {
    u <- 0
    while (a[v + 1] > a[t + 1] || (a[v + 1] == a[t + 1] && v > t)) {
      u <- t
      t <- nodes[[t + 1]]$parent
    }
    
    if (u != 0) {
      nodes[[v + 1]]$sib <- nodes[[u + 1]]$sib
      nodes[[u + 1]]$sib <- 0
      nodes[[u + 1]]$parent <- v
      nodes[[v + 1]]$child <- u
    } else {
      nodes[[v + 1]]$sib <- nodes[[t + 1]]$child
    }
    
    nodes[[t + 1]]$child <- v
    nodes[[v + 1]]$parent <- t
    t <- v
  }
  
  # Begin first traversal
  p <- nodes[[1]]$child
  n_count <- 0
  lam[1] <- -1
  
  # First traversal function
  traversal <- function() {
    while (TRUE) {
      # s3: Compute beta in the easy case
      n_count <<- n_count + 1
      pi_[p + 1] <<- n_count
      tau[n_count + 1] <<- 0
      lam[n_count + 1] <<- 1 + lam[bitwShiftR(n_count, 1) + 1]
      
      if (nodes[[p + 1]]$child != 0) {
        p <<- nodes[[p + 1]]$child
        next # Continue to next iteration
      }
      
      beta[p + 1] <<- n_count
      break
    }
    
    # s4: Compute tau, bottom-up
    while (TRUE) {
      tau[beta[p + 1]] <<- nodes[[p + 1]]$parent
      
      if (nodes[[p + 1]]$sib != 0) {
        p <<- nodes[[p + 1]]$sib
        return(TRUE)
      }
      
      p <<- nodes[[p + 1]]$parent
      
      # Compute beta in the hard case
      if (p != 0) {
        h <- lam[bitwAnd(n_count, -pi_[p + 1]) + 1]
        beta[p + 1] <<- bitwShiftL(bitwOr(bitwShiftR(n_count, h), 1), h)
      } else {
        return(FALSE) # Exit traversal
      }
    }
  }
  
  # Perform first traversal
  while (traversal()) {}
  
  # Begin second traversal
  p <- nodes[[1]]$child
  lam[1] <- lam[n_count + 1]
  pi_[1] <- 0
  beta[1] <- 0
  alfa[1] <- 0
  
  # Recursive function for second traversal
  compute_alfa <- function(node) {
    # s7: Compute alfa, top-down
    alfa[node + 1] <<- bitwOr(alfa[nodes[[node + 1]]$parent + 1], 
                              bitwAnd(beta[node + 1], -beta[node + 1]))
    
    if (nodes[[node + 1]]$child != 0) {
      compute_alfa(nodes[[node + 1]]$child)
    }
    
    # s8: Continue traversal
    if (nodes[[node + 1]]$sib != 0) {
      compute_alfa(nodes[[node + 1]]$sib)
    }
  }
  
  # Perform second (recursive) traversal if needed
  if (p != 0) {
    compute_alfa(p)
  }
  
  return(list(pi_ = pi_, beta = beta, alfa = alfa, tau = tau, lam = lam))
}

# Compute the nearest common ancestor (NCA) of two nodes x and y
nca <- function(x, y, beta, alfa, tau, lam, pi_) {
  # Find common height
  if (beta[x + 1] <= beta[y + 1]) {
    h <- lam[bitwAnd(beta[y + 1], -beta[x + 1] + 1) + 1]
  } else {
    h <- lam[bitwAnd(beta[x + 1], -beta[y + 1] + 1) + 1]
  }
  
  # Find true height
  k <- bitwAnd(bitwAnd(alfa[x + 1], alfa[y + 1]), 
               bitwNot(bitwShiftL(1, h)) + 1)
  h <- lam[bitwAnd(k, -k) + 1]
  
  # Find beta[z]
  j <- bitwShiftL(bitwOr(bitwShiftR(beta[x + 1], h), 1), h)
  
  # Find x' and y'
  if (j != beta[x + 1]) {
    l <- lam[bitwAnd(alfa[x + 1], bitwShiftL(1, h) - 1) + 1]
    x <- tau[bitwShiftL(bitwOr(bitwShiftR(beta[x + 1], l), 1), l) + 1]
  }
  
  if (j != beta[y + 1]) {
    l <- lam[bitwAnd(alfa[y + 1], bitwShiftL(1, h) - 1) + 1]
    y <- tau[bitwShiftL(bitwOr(bitwShiftR(beta[y + 1], l), 1), l) + 1]
  }
  
  # Find z
  if (pi_[x + 1] <= pi_[y + 1]) {
    return(x)
  } else {
    return(y)
  }
}

# Solve a test case using Schieber-Vishkin given values and queries
schiebervishkin <- function(n, values, queries) {
  results <- integer(length(queries))
  
  a <- c(.Machine$integer.max)
  r <- integer(n + 2)
  b <- integer(n + 2)
  
  big_n <- 1
  count <- 0
  oldx <- NULL
  
  for (i in 1:n) {
    x <- values[i]
    
    if (i > 1 && x != oldx) {
      a <- c(a, count)
      r[big_n + 1] <- i
      big_n <- big_n + 1
      count <- 0
    }
    
    b[i] <- big_n
    count <- count + 1
    oldx <- x
  }
  
  a <- c(a, count)
  r[big_n + 1] <- n + 1
  
  result_process <- process(big_n, a)
  pi_ <- result_process$pi_
  beta <- result_process$beta
  alfa <- result_process$alfa
  tau <- result_process$tau
  lam <- result_process$lam
  
  for (t in 1:length(queries)) {
    query <- queries[[t]]
    i <- query[1]
    j <- query[2]
    x <- b[i]
    y <- b[j]
    
    z <- 0
    if (x == y) {
      z <- j - i + 1
    } else {
      if (x + 1 != y) {
        z <- a[nca(x + 1, y - 1, beta, alfa, tau, lam, pi_) + 1]
      }
      z <- max(z, r[x + 1] - i, a[y + 1] - (r[y + 1] - j - 1))
    }
    results[t] <- z
  }
  
  return(results)
}

# Main function to run test cases
main <- function() {
  # Hard-coded test data
  test_cases <- list(
    list(
      n = 10,
      values = c(-1L, -1L, 1L, 1L, 1L, 1L, 3L, 10L, 10L, 10L),
      queries = list(c(2, 3), c(1, 10), c(5, 10)),
      expected = c(1L, 4L, 3L)
    )
  )
  
  for (idx in 1:length(test_cases)) {
    test_case <- test_cases[[idx]]
    n <- test_case$n
    values <- test_case$values
    queries <- test_case$queries
    expected <- test_case$expected
    
    cat("Test Case", idx, ":\n")
    cat("Size:", n, ", Queries:", length(queries), "\n")
    cat("Values:", paste(values, collapse = " "), "\n")
    
    results <- schiebervishkin(n, values, queries)
    
    cat("Queries and Results:\n")
    for (q_idx in 1:length(queries)) {
      query <- queries[[q_idx]]
      i <- query[1]
      j <- query[2]
      result <- results[q_idx]
      exp <- expected[q_idx]
      
      cat("Query:", i, j, "\n")
      cat("Result:", result, "(Expected:", exp, ")\n")
      if (result != exp) {
        cat("  WARNING: Result doesn't match expected output\n")
      }
    }
    
    cat("\n")
  }
}

# Run the main function
main()
Output:
Test Case 1 :
Size: 10 , Queries: 3 
Values: -1 -1 1 1 1 1 3 10 10 10 
Queries and Results:
Query: 2 3 
Result: 1 (Expected: 1 )
Query: 1 10 
Result: 4 (Expected: 4 )
Query: 5 10 
Result: 3 (Expected: 3 )




Translation of: Go
Translation of: Julia
# 20250716 Raku programming solution

# Node class for triply linked tree
class Node { has Int ($.child, $.sib, $.parent) is rw is default(0) }

# Result class to hold algorithm outputs
class Result { has Int (@.pi, @.beta, @.alfa, @.tau, @.lam) }

# Main processing function implementing Schieber-Vishkin algorithm
sub process(Int $n, @a) returns Result {
   my Int (@pi, @beta, @alfa, @tau, @lam); 
   my Node @nodes = Node.new xx ($n + 1);

   # Make triply linked tree
   my Int $t = 0;
   for $n...1 -> $v {
      my Int $u = 0;
      while @a[$v] > @a[$t] || (@a[$v] == @a[$t] && $v > $t) {
         $t = @nodes[ $u = $t ].parent;
      }
      if $u != 0 {
         (@nodes[$v].sib,@nodes[$u].sib,@nodes[$u].parent,@nodes[$v].child) =
          @nodes[$u].sib,             0,               $v,              $u;
      } else {
         @nodes[$v].sib = @nodes[$t].child;
      }
      @nodes[@nodes[$t].child = $v].parent = $t;
      $t = $v;
   }
   # First traversal
   my Int ($p, $n-count) = @nodes[0].child, 0;
   @lam[0] = -1;

   # Inner traversal function
   sub traversal() returns Bool {
      loop {
         @pi[$p] = ++$n-count;
         @tau[$n-count] = 0;
         @lam[$n-count] = 1 + @lam[$n-count +> 1];
         if @nodes[$p].child != 0 { $p = @nodes[$p].child and next }
         @beta[$p] = $n-count;
         last;
      }
      loop {
         @tau[@beta[$p]] = @nodes[$p].parent;
         if @nodes[$p].sib != 0 {
            $p = @nodes[$p].sib;
            return True;
         }
         $p = @nodes[$p].parent;
         if $p != 0 {
            my Int $h = @lam[$n-count +& (-@pi[$p])];
            @beta[$p] = (($n-count +> $h) +| 1) +< $h;
         } else {
            return False;
         }
      }
   }
   while traversal() { } # Perform first traversal

   # Second traversal
   (             $p,        @lam[0], @pi[0], @beta[0], @alfa[0] ) =
    @nodes[0].child, @lam[$n-count],      0,        0,        0 ;

   # Recursive function for computing alfa
   sub compute-alfa(Int $node) {
      @alfa[$node] = @alfa[@nodes[$node].parent] +| (@beta[$node] +& (-@beta[$node]));
      if @nodes[$node].child != 0 { compute-alfa(@nodes[$node].child) }
      if @nodes[$node].sib   != 0 { compute-alfa(@nodes[$node].sib) }
   }
   compute-alfa($p) if $p != 0;  # Perform second traversal if needed
   return Result.new(:pi(@pi),:beta(@beta),:alfa(@alfa),:tau(@tau),:lam(@lam));
}

# Compute nearest common ancestor
sub nca(Int $x is copy, Int $y is copy, @beta, @alfa, @tau, @lam, @pi) returns Int {
   my Int $h = @beta[$x] <= @beta[$y] ?? @lam[@beta[$y] +& (-@beta[$x])]
                                      !! @lam[@beta[$x] +& (-@beta[$y])];
   my Int $k = @alfa[$x] +& @alfa[$y] +& (-(1 +< $h));
   $h = @lam[$k +& (-$k)];
   my Int $j = ((@beta[$x] +> $h) +| 1) +< $h;
   if $j != @beta[$x] {
      my Int $l = @lam[@alfa[$x] +& ((1 +< $h) - 1)];
      $x = @tau[((@beta[$x] +> $l) +| 1) +< $l];
   }
   if $j != @beta[$y] {
      my Int $l = @lam[@alfa[$y] +& ((1 +< $h) - 1)];
      $y = @tau[((@beta[$y] +> $l) +| 1) +< $l];
   }
   return @pi[$x] <= @pi[$y] ?? $x !! $y;
}

# Generic solver function
sub solve-test-case-generic(Int $n, @values, @queries, &executor) {
   my Int @a = uint.Range.max; # 2**31 - 1
   my Int @r = 0 xx ($n + 2);
   my Int @b = 0 xx ($n + 2);
   my Int $big-n = 1;
   my Int $count = 0;
   my $oldx;
   for 1..$n -> $i {
      my Int $x = @values[$i - 1];
      if $i > 1 && (!$oldx.defined || $x != $oldx) {
         @a.push($count);
         @r[$big-n] = $i;
         $big-n++;
         $count = 0;
      }
      @b[$i] = $big-n;
      $count++;
      $oldx = $x;
   }
   @a.push($count);
   @r[$big-n] = $n + 1;

   given my Result $result = process($big-n, @a) {
      return executor(@queries, @a, @r, @b, .pi, .beta, .alfa, .tau, .lam)
   }
}

# Serial executor
sub run-serial( @queries, @a, @r, @b, @pi, @beta, @alfa, @tau, @lam) {
   return @queries.map: -> @query {
      my ($i, $j) = @query[0], @query[1];   # keep 1-based
      my ($x, $y) = @b[$i], @b[$j];

      do if $x == $y { # same block: contiguous run
         $j - $i + 1;
      } else {
         # 1) base = either nca-block or 0 if adjacent segments
         my Int $base = ($x + 1 != $y) 
                        ?? @a[ nca($x+1, $y-1, @beta, @alfa, @tau, @lam, @pi) ]
                        !! 0;
         # 2) include partial runs at both ends
         my Int $left  = @r[$x]      - $i;
         my Int $right = @a[$y] - @r[$y] + $j + 1;

         max($base, $left, $right); 
      }
   }
}

# Race executor ( mediocre implementation )
sub run-race(@queries, @a, @r, @b, @pi, @beta, @alfa, @tau, @lam) {
   return @queries.batch(1000).race.map({
      |(.map: -> @query {
         my ($i, $j) = @query[0], @query[1];
         my ($x, $y) = @b[$i], @b[$j];

         do if $x == $y {
            $j - $i + 1;
         } else {
            my $z = $x+1 != $y ?? @a[nca($x+1,$y-1,@beta,@alfa,@tau,@lam,@pi)] 
                               !! 0;
            max($z, @r[$x] - $i, @a[$y] - @r[$y] + $j + 1);
         }
      })
   });
}

# Async executor ( mediocre implementation ) 
sub run-async(@queries, @a, @r, @b, @pi, @beta, @alfa, @tau, @lam) {
   my @promises = @queries.batch(1000).map: -> @chunk {
      start {
         @chunk.map: -> @query {
            my ($i, $j) = @query[0], @query[1];
            my ($x, $y) = @b[$i], @b[$j];

            do if $x == $y {
               $j - $i + 1;
            } else {
               my $z = $x + 1 != $y 
                       ?? @a[nca($x + 1, $y - 1, @beta, @alfa, @tau, @lam, @pi)]
                       !! 0;
               max($z, @r[$x] - $i, @a[$y] - @r[$y] + $j + 1);
            }
         }
      }
   }
   return await(@promises).flat;
}

sub print-query-results(@queries, @results, @expected, Str $mode) {
   say "Queries and Results ($mode):";
   for @queries.kv -> $q-idx, @query {
      my ($i, $j) = @query[0], @query[1];
      my $result = @results[$q-idx];
      my $expected = @expected[$q-idx];
      say "Query: $i $j";
      say "Result: $result (Expected: $expected)";
      if $result != $expected {
         say "  WARNING: Result doesn't match expected output";
      }
   }
   say "";
}

my @test-cases = ({
   n        => 10,
   values   => [-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
   queries  => [[2, 3], [1, 10], [5, 10]],
   expected => [1, 4, 3]
},);
   
say "Output similar to the Go entry:\n";
for @test-cases.kv -> $idx, %test-case {
   say "Test Case {$idx + 1}:";
   my @results = solve-test-case-generic( %test-case<n>,
                                          %test-case<values>, 
                                          %test-case<queries>,
                                          &run-serial           );
   say "Result: {@results} (Expected: %test-case<expected>)";
}

say "\nOutput similar to the Julia entry:\n";

my @executors = [ 
   ['Sequential', &run-serial], 
   ['Race', &run-race], 
   ['Async', &run-async],
];

for @test-cases.kv -> $idx, %test-case {
   say "Test Case {$idx + 1}:";
   say "Size: {%test-case<n>}, Queries: {%test-case<queries>.elems}";
   say "Values: {%test-case<values>.join(' ')}\n";

   for @executors -> $executor {
      my ($label, $code) = $executor;
      my @results = solve-test-case-generic( %test-case<n>,
                                             %test-case<values>,
                                             %test-case<queries>,
                                             $code                );
      print-query-results( %test-case<queries>,  @results, 
                           %test-case<expected>,   $label);
   }
}

#`[[[[[[ nothing worthy of attention for now

# Demonstration of different approaches

my Int $n = 8000;
my @values = ^$n .map: { rand < 0.1 ?? -1 !! (1 + floor(rand * 1000)) };

my Int $query-count = 200;
my @queries = (^$query-count).map: { minmax (1..$n).pick, (1..$n).pick };

# Just test performance, don't compare expected outputs
say "Benchmarking on N=$n, Queries=$query-count\n";

for (
   [ 'Method 0: Plain serial processing',              &run-serial ],
   [ 'Method 1: Using .race (data parallelism)',         &run-race ],
   [ 'Method 2: Using start blocks (async processing)', &run-async ],
) -> ($label, $executor) {
   say $label;
   my $start-time = now;
   my @results = solve-test-case-generic($n, @values, @queries, $executor);
   my $elapsed = now - $start-time;
   say "Completed in {$elapsed.round(0.001)} seconds\n";
}

#]]]]]]

You may Attempt This Online!

Works with: Rust
Translation of: Python
use std::cmp;

#[derive(Clone, Default)]
struct Node {
    child: usize,
    sib: usize,
    parent: usize,
}

fn process(n: usize, a: &mut Vec<i32>) -> (Vec<usize>, Vec<usize>, Vec<usize>, Vec<usize>, Vec<i32>) {
    let mut pi = vec![0; n + 1];
    let mut beta = vec![0; n + 1];
    let mut alfa = vec![0; n + 1];
    let mut tau = vec![0; n + 1];
    let mut lam = vec![0; n + 1];
    lam[0] = -1; // Change this to i32 instead of usize
    let mut nodes = vec![Node::default(); n + 1];

    // Make triply linked tree
    let mut t = 0;
    for v in (1..=n).rev() {
        let mut u = 0;
        while a[v] > a[t] || (a[v] == a[t] && v > t) {
            u = t;
            t = nodes[t].parent;
        }
        
        if u != 0 {
            nodes[v].sib = nodes[u].sib;
            nodes[u].sib = 0;
            nodes[u].parent = v;
            nodes[v].child = u;
        } else {
            nodes[v].sib = nodes[t].child;
        }
        
        nodes[t].child = v;
        nodes[v].parent = t;
        t = v;
    }

    // Begin first traversal
    let mut p = nodes[0].child;
    let mut n_count = 0;

    // First traversal loop (replaces goto-based control flow)
    loop {
        // s3: Compute beta in the easy case
        n_count += 1;
        pi[p] = n_count;
        tau[n_count] = 0;
        lam[n_count] = 1 + lam[n_count >> 1];
        
        if nodes[p].child != 0 {
            p = nodes[p].child;
            continue;
        }
        
        beta[p] = n_count;

        // s4: Compute tau, bottom-up
        loop {
            tau[beta[p]] = nodes[p].parent;
            
            if nodes[p].sib != 0 {
                p = nodes[p].sib;
                break; // Go back to s3
            }
            
            p = nodes[p].parent;
            
            // Compute beta in the hard case
            if p != 0 {
                let h = lam[(n_count & (!pi[p] + 1)) as usize];
                beta[p] = ((n_count >> h as usize) | 1) << h as usize;
            } else {
                // Exit traversal
                break;
            }
        }
        
        if p == 0 {
            break;
        }
    }

    // Begin second traversal
    p = nodes[0].child;
    lam[0] = lam[n_count];
    pi[0] = 0;
    beta[0] = 0;
    alfa[0] = 0;

    // Recursive function for second traversal
    fn compute_alfa(
        p: usize,
        nodes: &[Node],
        alfa: &mut [usize],
        beta: &[usize],
    ) {
        // s7: Compute alfa, top-down
        alfa[p] = alfa[nodes[p].parent] | (beta[p] & (!beta[p] + 1));
        
        if nodes[p].child != 0 {
            compute_alfa(nodes[p].child, nodes, alfa, beta);
        }
        
        // s8: Continue traversal
        if nodes[p].sib != 0 {
            compute_alfa(nodes[p].sib, nodes, alfa, beta);
        }
    }

    // Perform second traversal
    if p != 0 {
        compute_alfa(p, &nodes, &mut alfa, &beta);
    }

    (pi, beta, alfa, tau, lam)
}

fn nca(
    mut x: usize,
    mut y: usize,
    beta: &[usize],
    alfa: &[usize],
    tau: &[usize],
    lam: &[i32], // Changed to i32
    pi: &[usize],
) -> usize {
    // Find common height
    let h = if beta[x] <= beta[y] {
        lam[(beta[y] & (!beta[x] + 1)) as usize]
    } else {
        lam[(beta[x] & (!beta[y] + 1)) as usize]
    };
    
    // Find true height
    let k = alfa[x] & alfa[y] & (!(1 << h as usize) + 1);
    let h = lam[(k & (!k + 1)) as usize];
    
    // Find beta[z]
    let j = ((beta[x] >> h as usize) | 1) << h as usize;
    
    // Find x' and y'
    if j != beta[x] {
        let l = lam[(alfa[x] & ((1 << h as usize) - 1)) as usize];
        x = tau[((beta[x] >> l as usize) | 1) << l as usize];
    }
    
    if j != beta[y] {
        let l = lam[(alfa[y] & ((1 << h as usize) - 1)) as usize];
        y = tau[((beta[y] >> l as usize) | 1) << l as usize];
    }
    
    // Find z
    if pi[x] <= pi[y] { x } else { y }
}

fn solve_test_case(
    n: usize,
    values: &[i32],
    queries: &[(usize, usize)],
) -> Vec<i32> {
    let mut results = Vec::new();
    
    let mut a = vec![i32::MAX];  // A[0]
    let mut r = vec![0; n + 2];
    let mut b = vec![0; n + 2];
    
    let mut big_n = 1;
    let mut count = 0;
    let mut oldx = None;
    
    for i in 1..=n {
        let x = values[i - 1];
        
        if i > 1 && Some(x) != oldx {
            a.push(count);
            r[big_n] = i;
            big_n += 1;
            count = 0;
        }
        
        b[i] = big_n;
        count += 1;
        oldx = Some(x);
    }
    
    a.push(count);
    r[big_n] = n + 1;
    
    let (pi, beta, alfa, tau, lam) = process(big_n, &mut a);
    
    for &(i, j) in queries {
        let x = b[i];
        let y = b[j];
        
        let z = if x == y {
            (j - i + 1) as i32
        } else {
            let mut z = if x + 1 != y {
                a[nca(x + 1, y - 1, &beta, &alfa, &tau, &lam, &pi)]
            } else {
                0
            };
            
            z = cmp::max(z, cmp::max(
                (r[x] - i) as i32,
                a[y] - (r[y] - j - 1) as i32
            ));
            
            z
        };
        
        results.push(z);
    }
    
    results
}

fn main() {
    // Hard-coded test data
    let test_cases = [
        (
            10,
            vec![-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
            vec![(2, 3), (1, 10), (5, 10)],
            vec![1, 4, 3]
        )
    ];
    
    for (idx, (n, values, queries, expected)) in test_cases.iter().enumerate() {
        println!("Test Case {}:", idx + 1);
        println!("Size: {}, Queries: {}", n, queries.len());
        print!("Values: ");
        for v in values {
            print!("{} ", v);
        }
        println!();
        
        let results = solve_test_case(*n, values, queries);
        
        println!("Queries and Results:");
        // Fixed iterator pattern
        for q_idx in 0..queries.len() {
            let (i, j) = queries[q_idx];
            let result = results[q_idx];
            let exp = expected[q_idx];
            
            println!("Query: {} {}", i, j);
            println!("Result: {} (Expected: {})", result, exp);
            if result != exp {
                println!("  WARNING: Result doesn't match expected output");
            }
        }
        
        println!();
    }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10 
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)
Works with: Scala version 2.13.8
Translation of: Java
import scala.collection.mutable.ArrayBuffer
import scala.util.control.Breaks._


object Main {
  case class Node(var child: Int = 0, var sib: Int = 0, var parent: Int = 0)
  
  case class Result(pi: Array[Int], beta: Array[Int], alfa: Array[Int], tau: Array[Int], lam: Array[Int])
  
  case class TestCase(n: Int, values: Array[Int], queries: Array[Array[Int]], expected: Array[Int])
  
  case class TraversalState(var p: Int, var n: Int)

  def process(N: Int, A: Array[Int]): Result = {
    val pi = Array.ofDim[Int](N + 1)
    val beta = Array.ofDim[Int](N + 1)
    val alfa = Array.ofDim[Int](N + 1)
    val tau = Array.ofDim[Int](N + 1)
    val lam = Array.ofDim[Int](N + 1)
    val nodes = Array.fill(N + 1)(Node())
    
    // Make triply linked tree
    var t = 0
    for (v <- N to 1 by -1) {
      var u = 0
      while (A(v) > A(t) || (A(v) == A(t) && v > t)) {
        u = t
        t = nodes(t).parent
      }
      
      if (u != 0) {
        nodes(v).sib = nodes(u).sib
        nodes(u).sib = 0
        nodes(u).parent = v
        nodes(v).child = u
      } else {
        nodes(v).sib = nodes(t).child
      }
      
      nodes(t).child = v
      nodes(v).parent = t
      t = v
    }
    
    // Begin first traversal
    var p = nodes(0).child
    var n = 0
    lam(0) = -1
    
    // Using a mutable object to simulate pass-by-reference behavior
    
    val state = TraversalState(p, n)
    
    while (traversal(nodes, state, pi, beta, tau, lam)) {
      // Continue traversal
      n = state.n
      p = state.p
    }
    
    // Begin second traversal
    p = nodes(0).child
    lam(0) = lam(n)
    pi(0) = 0
    beta(0) = 0
    alfa(0) = 0
    
    // Perform second traversal
    if (p != 0) {
      compute_alfa(nodes, p, alfa, beta)
    }
    
    Result(pi, beta, alfa, tau, lam)
  }
  
  def traversal(nodes: Array[Node], state: TraversalState, pi: Array[Int], beta: Array[Int], tau: Array[Int], lam: Array[Int]): Boolean = {
    // s3: Compute beta in the easy case
    breakable({
    while (true) {
      state.n += 1
      pi(state.p) = state.n
      tau(state.n) = 0
      lam(state.n) = 1 + lam(state.n >> 1)
      
      breakable({
      if (nodes(state.p).child != 0) {
        state.p = nodes(state.p).child
        return true
      }
      });
      
      beta(state.p) = state.n
      break;  //break
    }
    });
    
    // s4: Compute tau, bottom-up
    while (true) {
      tau(beta(state.p)) = nodes(state.p).parent
      
      if (nodes(state.p).sib != 0) {
        state.p = nodes(state.p).sib
        return true  // Go back to s3
      }
      
      state.p = nodes(state.p).parent
      
      // Compute beta in the hard case
      if (state.p != 0) {
        val h = lam(state.n & -pi(state.p))
        beta(state.p) = ((state.n >> h) | 1) << h
      } else {
        return false  // Exit traversal
      }
    }
    
    false // Should never reach here due to returns above
  }
  
  def compute_alfa(nodes: Array[Node], node: Int, alfa: Array[Int], beta: Array[Int]): Unit = {
    // s7: Compute alfa, top-down
    alfa(node) = alfa(nodes(node).parent) | (beta(node) & -beta(node))
    
    if (nodes(node).child != 0) {
      compute_alfa(nodes, nodes(node).child, alfa, beta)
    }
    
    // s8: Continue traversal
    if (nodes(node).sib != 0) {
      compute_alfa(nodes, nodes(node).sib, alfa, beta)
    }
  }
  
  def nca(x: Int, y: Int, beta: Array[Int], alfa: Array[Int], tau: Array[Int], lam: Array[Int], pi: Array[Int]): Int = {
    // Find common height
    val h = if (beta(x) <= beta(y)) {
      lam(beta(y) & -beta(x))
    } else {
      lam(beta(x) & -beta(y))
    }
    
    // Find true height
    val k = alfa(x) & alfa(y) & -(1 << h)
    val trueHeight = lam(k & -k)
    
    // Find beta(z)
    val j = ((beta(x) >> trueHeight) | 1) << trueHeight
    
    // Find x' and y'
    var newX = x
    var newY = y
    
    if (j != beta(x)) {
      val l = lam(alfa(x) & ((1 << trueHeight) - 1))
      newX = tau(((beta(x) >> l) | 1) << l)
    }
    
    if (j != beta(y)) {
      val l = lam(alfa(y) & ((1 << trueHeight) - 1))
      newY = tau(((beta(y) >> l) | 1) << l)
    }
    
    // Find z
    if (pi(newX) <= pi(newY)) newX else newY
  }
  
  def solve_test_case(n: Int, values: Array[Int], queries: Array[Array[Int]]): ArrayBuffer[Int] = {
    val results = ArrayBuffer[Int]()
    
    val A = Array.ofDim[Int](n + 2)
    A(0) = Int.MaxValue  // A(0)
    val R = Array.ofDim[Int](n + 2)
    val B = Array.ofDim[Int](n + 2)
    
    var N = 1
    var count = 0
    var oldx: Option[Int] = None
    
    for (i <- 1 to n) {
      val x = values(i - 1)
      
      if (i > 1 && (oldx.isEmpty || x != oldx.get)) {
        A(N) = count
        R(N) = i
        N += 1
        count = 0
      }
      
      B(i) = N
      count += 1
      oldx = Some(x)
    }
    
    A(N) = count
    R(N) = n + 1
    
    val result = process(N, A)
    val pi = result.pi
    val beta = result.beta
    val alfa = result.alfa
    val tau = result.tau
    val lam = result.lam
    
    for (query <- queries) {
      val i = query(0)
      val j = query(1)
      val x = B(i)
      val y = B(j)
      
      val z = if (x == y) {
        j - i + 1
      } else {
        val commonLength = if (x + 1 != y) {
          A(nca(x + 1, y - 1, beta, alfa, tau, lam, pi))
        } else {
          0
        }
        
        math.max(commonLength, math.max(R(x) - i, A(y) - R(y) + j + 1))
      }
      
      results += z
    }
    
    results
  }
  
  def main(args: Array[String]): Unit = {
    // Hard-coded test data
    val testCases = List(
      TestCase(
        10,
        Array(-1, -1, 1, 1, 1, 1, 3, 10, 10, 10),
        Array(Array(2, 3), Array(1, 10), Array(5, 10)),
        Array(1, 4, 3)
      )
    )
    
    for ((test, idx) <- testCases.zipWithIndex) {
      val n = test.n
      val values = test.values
      val queries = test.queries
      val expected = test.expected
      
      println(s"Test Case ${idx + 1}:")
      println(s"Size: $n, Queries: ${queries.length}")
      print("Values: ")
      println(values.mkString(" "))
      
      val results = solve_test_case(n, values, queries)
      
      println("Queries and Results:")
      for (q_idx <- queries.indices) {
        val query = queries(q_idx)
        val result = results(q_idx)
        val exp = expected(q_idx)
        
        println(s"Query: ${query(0)} ${query(1)}")
        println(s"Result: $result (Expected: $exp)")
        if (result != exp) {
          println("  WARNING: Result doesn't match expected output")
        }
      }
      
      println()
    }
  }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)


Warning:The wrong Swift code needs to be corrected.
Works with: Swift
Translation of: Java
import Foundation

class Node {
    var child: Int = 0
    var sib: Int = 0
    var parent: Int = 0
}

struct Result {
    var pi: [Int]
    var beta: [Int]
    var alfa: [Int]
    var tau: [Int]
    var lam: [Int]
}

// These variables are used to simulate the nonlocal variables
private var p: Int = 0
private var n: Int = 0

func getP() -> Int {
    return p
}

func getN() -> Int {
    return n
}

func process(N: Int, A: [Int]) -> Result {
    var pi = Array(repeating: 0, count: N + 1)
    var beta = Array(repeating: 0, count: N + 1)
    var alfa = Array(repeating: 0, count: N + 1)
    var tau = Array(repeating: 0, count: N + 1)
    var lam = Array(repeating: 0, count: N + 1)
    let nodes = Array(repeating: Node(), count: N + 1)
    
    // Make triply linked tree
    var t = 0
    for v in stride(from: N, to: 0, by: -1) {
        var u = 0
        while A[v] > A[t] || (A[v] == A[t] && v > t) {
            u = t
            t = nodes[t].parent
        }
        
        if u != 0 {
            nodes[v].sib = nodes[u].sib
            nodes[u].sib = 0
            nodes[u].parent = v
            nodes[v].child = u
        } else {
            nodes[v].sib = nodes[t].child
        }
        
        nodes[t].child = v
        nodes[v].parent = t
        t = v
    }
    
    // Begin first traversal
    var p = nodes[0].child
    var n = 0
    lam[0] = -1
    
    while traversal(nodes: nodes, initialP: p, initialN: n, pi: &pi, beta: &beta, tau: &tau, lam: &lam) {
        // Continue traversal
        n = getN()
        p = getP()
    }
    
    // Begin second traversal
    p = nodes[0].child
    lam[0] = lam[n]
    pi[0] = 0
    beta[0] = 0
    alfa[0] = 0
    
    // Perform second traversal
    if p != 0 {
        compute_alfa(nodes: nodes, node: p, alfa: &alfa, beta: beta)
    }
    
    return Result(pi: pi, beta: beta, alfa: alfa, tau: tau, lam: lam)
}

func traversal(nodes: [Node], initialP: Int, initialN: Int, pi: inout [Int], beta: inout [Int], tau: inout [Int], lam: inout [Int]) -> Bool {
    p = initialP
    n = initialN
    
    // s3: Compute beta in the easy case
    while true {
        n += 1
        pi[p] = n
        tau[n] = 0
        lam[n] = 1 + lam[n >> 1]
        
        if nodes[p].child != 0 {
            p = nodes[p].child
            continue
        }
        
        beta[p] = n
        break
    }
    
    // s4: Compute tau, bottom-up
    while true {
        tau[beta[p]] = nodes[p].parent
        
        if nodes[p].sib != 0 {
            p = nodes[p].sib
            return true  // Go back to s3
        }
        
        p = nodes[p].parent
        
        // Compute beta in the hard case
        if p != 0 {
            let h = lam[n & -pi[p]]
            beta[p] = ((n >> h) | 1) << h
        } else {
            return false  // Exit traversal
        }
    }
}

func compute_alfa(nodes: [Node], node: Int, alfa: inout [Int], beta: [Int]) {
    // s7: Compute alfa, top-down
    alfa[node] = alfa[nodes[node].parent] | (beta[node] & -beta[node])
    
    if nodes[node].child != 0 {
        compute_alfa(nodes: nodes, node: nodes[node].child, alfa: &alfa, beta: beta)
    }
    
    // s8: Continue traversal
    if nodes[node].sib != 0 {
        compute_alfa(nodes: nodes, node: nodes[node].sib, alfa: &alfa, beta: beta)
    }
}

func nca(x: Int, y: Int, beta: [Int], alfa: [Int], tau: [Int], lam: [Int], pi: [Int]) -> Int {
    // Find common height
    var h: Int
    if beta[x] <= beta[y] {
        h = lam[beta[y] & -beta[x]]
    } else {
        h = lam[beta[x] & -beta[y]]
    }
    
    // Find true height
    let k = alfa[x] & alfa[y] & -(1 << h)
    h = lam[k & -k]
    
    // Find beta[z]
    let j = ((beta[x] >> h) | 1) << h
    
    // Find x' and y'
    var x = x
    var y = y
    
    if j != beta[x] {
        let l = lam[alfa[x] & ((1 << h) - 1)]
        x = tau[((beta[x] >> l) | 1) << l]
    }
    
    if j != beta[y] {
        let l = lam[alfa[y] & ((1 << h) - 1)]
        y = tau[((beta[y] >> l) | 1) << l]
    }
    
    // Find z
    let z = (pi[x] <= pi[y]) ? x : y
    return z
}

func solve_test_case(n: Int, values: [Int], queries: [[Int]]) -> [Int] {
    var results: [Int] = []
    
    var A = Array(repeating: 0, count: n + 2)
    A[0] = Int.max  // A[0]
    var R = Array(repeating: 0, count: n + 2)
    var B = Array(repeating: 0, count: n + 2)
    
    var N = 1
    var count = 0
    var oldx: Int? = nil
    
    for i in 1...n {
        let x = values[i - 1]
        
        if i > 1 && (oldx == nil || x != oldx!) {
            A[N] = count
            R[N] = i
            N += 1
            count = 0
        }
        
        B[i] = N
        count += 1
        oldx = x
    }
    
    A[N] = count
    R[N] = n + 1
    
    let result = process(N: N, A: A)
    let pi = result.pi
    let beta = result.beta
    let alfa = result.alfa
    let tau = result.tau
    let lam = result.lam
    
    for query in queries {
        let i = query[0]
        let j = query[1]
        let x = B[i]
        let y = B[j]
        
        var z: Int
        if x == y {
            z = j - i + 1
        } else {
            if x + 1 != y {
                z = A[nca(x: x + 1, y: y - 1, beta: beta, alfa: alfa, tau: tau, lam: lam, pi: pi)]
            } else {
                z = 0
            }
            
            z = max(z, max(R[x] - i, A[y] - R[y] + j + 1))
        }
        
        results.append(z)
    }
    
    return results
}

struct TestCase {
    let n: Int
    let values: [Int]
    let queries: [[Int]]
    let expected: [Int]
    
    init(n: Int, values: [Int], queries: [[Int]], expected: [Int]) {
        self.n = n
        self.values = values
        self.queries = queries
        self.expected = expected
    }
}

// Main program
func main() {
    // Hard-coded test data
    let testCases: [TestCase] = [
        TestCase(
            n: 10,
            values: [-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
            queries: [[2, 3], [1, 10], [5, 10]],
            expected: [1, 4, 3]
        )
    ]
    
    for (idx, test) in testCases.enumerated() {
        let n = test.n
        let values = test.values
        let queries = test.queries
        let expected = test.expected
        
        print("Test Case \(idx + 1):")
        print("Size: \(n), Queries: \(queries.count)")
        print("Values: \(values.map { String($0) }.joined(separator: " "))")
        
        let results = solve_test_case(n: n, values: values, queries: queries)
        
        print("Queries and Results:")
        for q_idx in 0..<queries.count {
            let query = queries[q_idx]
            let result = results[q_idx]
            let exp = expected[q_idx]
            
            print("Query: \(query[0]) \(query[1])")
            print("Result: \(result) (Expected: \(exp))")
            if result != exp {
                print("  WARNING: Result doesn't match expected output")
            }
        }
        
        print()
    }
}

main()
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
<It takes too long to complete the calculation>


Translation of: Python
Library: Wren-dynamic
Library: Wren-math
import "./dynamic" for Struct
import "./math" for Math

var Node = Struct.create("Node", ["child", "sib", "parent"])

var Result = Struct.create("Result", ["pi", "beta", "alfa", "tau", "lam"])

var process = Fn.new { |N, A|
    var pi    = List.filled(N + 1, 0)
    var beta  = List.filled(N + 1, 0)
    var alfa  = List.filled(N + 1, 0)
    var tau   = List.filled(N + 1, 0)
    var lam   = List.filled(N + 1, 0)
    var nodes = List.filled(N + 1, null)
    for (i in 0..N) nodes[i] = Node.new(0, 0, 0)

    // Make triply linked tree.
    var t = 0
    for (v in N..1) {
        var u = 0
        while (A[v] > A[t] || (A[v] == A[t] && v > t)) {
            u = t
            t = nodes[t].parent
        }
        if (u != 0) {
            nodes[v].sib = nodes[u].sib
            nodes[u].sib = 0
            nodes[u].parent = v
            nodes[v].child = u
        } else {
            nodes[v].sib = nodes[t].child
        }
        nodes[t].child = v
        nodes[v].parent = t
        t = v
    }

    // Begin first traversal.
    var p = nodes[0].child
    var n = 0
    lam[0] = -1

    var traversal = Fn.new {
        // s3: Compute beta in the easy case.
        while (true) {
            n = n + 1
            pi[p] = n
            tau[n] = 0
            lam[n] = 1 + lam[n >> 1]

            if (nodes[p].child != 0) {
                p = nodes[p].child
                continue
            }

            beta[p] = n
            break
        }

        // s4: Compute tau, bottom-up.
        while (true) {
            tau[beta[p]] = nodes[p].parent

            if (nodes[p].sib != 0) {
                p = nodes[p].sib
                return true  // go back to s3
            }

            p = nodes[p].parent

            // Compute beta in the hard case.
            if (p != 0) {
                var h = lam[n & ~(pi[p] - 1)]
                beta[p] = ((n >> h) | 1) << h
            } else {
                return false  // exit traversal
            }
        }
    }

    // Perform first traversal.
    while (traversal.call()) {}

    // Begin second traversal.
    p = nodes[0].child
    lam[0] = lam[n]
    pi[0] = beta[0] = alfa[0] = 0

    var computeAlfa // recursive 
    computeAlfa = Fn.new { |node|
        // s7: Compute alfa, top-down.
        alfa[node] = alfa[nodes[node].parent] | (beta[node] & ~(beta[node] - 1))

        if (nodes[node].child != 0) computeAlfa.call(nodes[node].child)

        // s8: Continue traversal.
        if (nodes[node].sib != 0) computeAlfa.call(nodes[node].sib)
    }

    // Perform second traversal.
    if (p != 0) computeAlfa.call(p)

    return Result.new(pi, beta, alfa, tau, lam)
}

var nca = Fn.new { |x, y, beta, alfa, tau, lam, pi|
    // Find common height.
    var h
    if (beta[x] <= beta[y]) {
        h = lam[beta[y] & ~(beta[x] - 1)]
    } else {
        h = lam[beta[x] & ~(beta[y] - 1)]
    }

    // Find true height.
    var k = alfa[x] & alfa[y] & ~((1 << h) - 1)
    h = lam[k & ~(k - 1)]

    // Find beta[z].
    var j = ((beta[x] >> h) | 1) << h

    // Find x' and y'.
    var l
    if (j != beta[x]) {
        l = lam[alfa[x] & ((1 << h) - 1)]
        x = tau[((beta[x] >> l) | 1) << l]
    }

    if (j != beta[y]) {
        l = lam[alfa[y] & ((1 << h) - 1)]
        y = tau[((beta[y] >> l) | 1) << l]
    }

    // Find z.
    var z = pi[x] <= pi[y] ? x : y
    return z
}

var solveTestCase = Fn.new { |n, values, queries|
    var results = []

    var A = [Num.maxSafeInteger]
    var R = List.filled(n + 2, 0)
    var B = List.filled(n + 2, 0)

    var N = 1
    var count = 0
    var oldx = null

    for (i in 1..n) {
        var x = values[i - 1]

        if (i > 1 && x != oldx) {
            A.add(count)
            R[N] = i
            N = N + 1
            count = 0
        }

        B[i] = N
        count = count + 1
        oldx = x
    }

    A.add(count)
    R[N] = n + 1

    var r = process.call(N, A)

    for (t in queries) {
        var i = t[0]
        var j = t[1]
        var x = B[i]
        var y = B[j]
        var z

        if (x == y) {
            z = j - i + 1
        } else {
            if (x + 1 != y) {
                z = A[nca.call(x + 1, y - 1, r.beta, r.alfa, r.tau, r.lam, r.pi)]
            } else {
                z = 0
            }
            z = Math.max(z, Math.max(R[x] - i, A[y] - R[y] + j + 1))
        }
        results.add(z)
    }
    return results
}

// Hard-coded test data.
var testCases = [
    {
        "n": 10,
        "values": [-1, -1, 1, 1, 1, 1, 3, 10, 10, 10],
        "queries": [[2, 3], [1, 10], [5, 10]],
        "expected": [1, 4, 3]
    }
]

var idx = 0
for (test in testCases) {
    var n = test["n"]
    var values = test["values"]
    var queries = test["queries"]
    var expected = test["expected"]

    System.print("Test Case %(idx + 1):")
    System.print("Size: %(n), Queries: %(queries.count)")
    System.print("Values: %(values.join(" "))")

    var results = solveTestCase.call(n, values, queries)

    System.print("Queries and Results:")
    for (qIdx in 0...queries.count) {
        var q = queries[qIdx]
        var i = q[0]
        var j = q[1]
        var result = results[qIdx]
        var exp = expected[qIdx]
        System.print("Query: %(i) %(j)")
        System.print("Result: %(result) (Expected: %(exp))")
        if (result != exp) {
            System.print("  WARNING: Result doesn't match expected output")
        }
    }
    idx = idx + 1
    System.print()
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)
Works with: Zig version 0.14.1
Translation of: Rust
const std = @import("std");
const print = std.debug.print;
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;

const Node = struct {
    child: usize = 0,
    sib: usize = 0,
    parent: usize = 0,
};

const ProcessResult = struct {
    pi: []usize,
    beta: []usize,
    alfa: []usize,
    tau: []usize,
    lam: []i32,
};

fn process(allocator: Allocator, n: usize, a: []i32) !ProcessResult {
    var pi = try allocator.alloc(usize, n + 1);
    var beta = try allocator.alloc(usize, n + 1);
    var alfa = try allocator.alloc(usize, n + 1);
    var tau = try allocator.alloc(usize, n + 1);
    var lam = try allocator.alloc(i32, n + 1);
    
    @memset(pi, 0);
    @memset(beta, 0);
    @memset(alfa, 0);
    @memset(tau, 0);
    @memset(lam, 0);
    
    lam[0] = -1;
    
    var nodes = try allocator.alloc(Node, n + 1);
    for (nodes) |*node| {
        node.* = Node{};
    }

    // Make triply linked tree
    var t: usize = 0;
    var v: usize = n;
    while (v >= 1) : (v -= 1) {
        var u: usize = 0;
        while (a[v] > a[t] or (a[v] == a[t] and v > t)) {
            u = t;
            t = nodes[t].parent;
        }
        
        if (u != 0) {
            nodes[v].sib = nodes[u].sib;
            nodes[u].sib = 0;
            nodes[u].parent = v;
            nodes[v].child = u;
        } else {
            nodes[v].sib = nodes[t].child;
        }
        
        nodes[t].child = v;
        nodes[v].parent = t;
        t = v;
    }

    // Begin first traversal
    var p = nodes[0].child;
    var n_count: usize = 0;

    // First traversal loop
    while (true) {
        // s3: Compute beta in the easy case
        n_count += 1;
        pi[p] = n_count;
        tau[n_count] = 0;
        lam[n_count] = 1 + lam[n_count >> 1];
        
        if (nodes[p].child != 0) {
            p = nodes[p].child;
            continue;
        }
        
        beta[p] = n_count;

        // s4: Compute tau, bottom-up
        while (true) {
            tau[beta[p]] = nodes[p].parent;
            
            if (nodes[p].sib != 0) {
                p = nodes[p].sib;
                break; // Go back to s3
            }
            
            p = nodes[p].parent;
            
            // Compute beta in the hard case
            if (p != 0) {
                const h = lam[(n_count & (~pi[p] + 1))];
                beta[p] = ((n_count >> @intCast(h)) | 1) << @intCast(h);
            } else {
                // Exit traversal
                break;
            }
        }
        
        if (p == 0) {
            break;
        }
    }

    // Begin second traversal
    p = nodes[0].child;
    lam[0] = lam[n_count];
    pi[0] = 0;
    beta[0] = 0;
    alfa[0] = 0;

    // Perform second traversal
    if (p != 0) {
        computeAlfa(p, nodes, alfa, beta);
    }

    defer allocator.free(nodes);
    
    return ProcessResult{
        .pi = pi,
        .beta = beta,
        .alfa = alfa,
        .tau = tau,
        .lam = lam,
    };
}

fn computeAlfa(p: usize, nodes: []const Node, alfa: []usize, beta: []const usize) void {
    // s7: Compute alfa, top-down
    alfa[p] = alfa[nodes[p].parent] | (beta[p] & (~beta[p] + 1));
    
    if (nodes[p].child != 0) {
        computeAlfa(nodes[p].child, nodes, alfa, beta);
    }
    
    // s8: Continue traversal
    if (nodes[p].sib != 0) {
        computeAlfa(nodes[p].sib, nodes, alfa, beta);
    }
}

fn nca(
    x_param: usize,
    y_param: usize,
    beta: []const usize,
    alfa: []const usize,
    tau: []const usize,
    lam: []const i32,
    pi: []const usize,
) usize {
    var x = x_param;
    var y = y_param;
    
    // Find common height
    var h = if (beta[x] <= beta[y])
        lam[(beta[y] & (~beta[x] + 1))]
    else
        lam[(beta[x] & (~beta[y] + 1))];
    
    // Find true height
    const k = alfa[x] & alfa[y] & (~(@as(usize, 1) << @intCast(h)) + 1);
    h = lam[(k & (~k + 1))];
    
    // Find beta[z]
    const j = ((beta[x] >> @intCast(h)) | 1) << @intCast(h);
    
    // Find x' and y'
    if (j != beta[x]) {
        const l = lam[(alfa[x] & ((@as(usize, 1) << @intCast(h)) - 1))];
        x = tau[((beta[x] >> @intCast(l)) | 1) << @intCast(l)];
    }
    
    if (j != beta[y]) {
        const l = lam[(alfa[y] & ((@as(usize, 1) << @intCast(h)) - 1))];
        y = tau[((beta[y] >> @intCast(l)) | 1) << @intCast(l)];
    }
    
    // Find z
    return if (pi[x] <= pi[y]) x else y;
}

fn solveTestCase(
    allocator: Allocator,
    n: usize,
    values: []const i32,
    queries: []const [2]usize,
) ![]i32 {
    var results = ArrayList(i32).init(allocator);
    defer results.deinit();
    
    var a = ArrayList(i32).init(allocator);
    defer a.deinit();
    try a.append(std.math.maxInt(i32)); // A[0]
    
    var r = try allocator.alloc(usize, n + 2);
    defer allocator.free(r);
    var b = try allocator.alloc(usize, n + 2);
    defer allocator.free(b);
    
    @memset(r, 0);
    @memset(b, 0);
    
    var big_n: usize = 1;
    var count: i32 = 0;
    var oldx: ?i32 = null;
    
    for (1..n + 1) |i| {
        const x = values[i - 1];
        
        if (i > 1 and (oldx == null or x != oldx.?)) {
            try a.append(count);
            r[big_n] = i;
            big_n += 1;
            count = 0;
        }
        
        b[i] = big_n;
        count += 1;
        oldx = x;
    }
    
    try a.append(count);
    r[big_n] = n + 1;
    
    const process_result = try process(allocator, big_n, a.items);
    defer {
        allocator.free(process_result.pi);
        allocator.free(process_result.beta);
        allocator.free(process_result.alfa);
        allocator.free(process_result.tau);
        allocator.free(process_result.lam);
    }
    
    for (queries) |query| {
        const i = query[0];
        const j = query[1];
        const x = b[i];
        const y = b[j];
        
        const z = if (x == y)
            @as(i32, @intCast(j - i + 1))
        else blk: {
            var z_val: i32 = if (x + 1 != y)
                a.items[nca(x + 1, y - 1, process_result.beta, process_result.alfa, process_result.tau, process_result.lam, process_result.pi)]
            else
                0;
            
            z_val = @max(z_val, @max(
                @as(i32, @intCast(r[x] - i)),
                a.items[y] - @as(i32, @intCast(r[y] - j - 1))
            ));
            
            break :blk z_val;
        };
        
        try results.append(z);
    }
    
    return results.toOwnedSlice();
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    // Hard-coded test data
    const TestCase = struct {
        n: usize,
        values: []const i32,
        queries: []const [2]usize,
        expected: []const i32,
    };
    
    const test_cases = [_]TestCase{
        TestCase{
            .n = 10,
            .values = &[_]i32{ -1, -1, 1, 1, 1, 1, 3, 10, 10, 10 },
            .queries = &[_][2]usize{ [_]usize{ 2, 3 }, [_]usize{ 1, 10 }, [_]usize{ 5, 10 } },
            .expected = &[_]i32{ 1, 4, 3 },
        },
    };
    
    for (test_cases, 0..) |test_case, idx| {
        print("Test Case {}:\n", .{idx + 1});
        print("Size: {}, Queries: {}\n", .{ test_case.n, test_case.queries.len });
        print("Values: ",  .{});
        for (test_case.values) |v| {
            print("{} ", .{v});
        }
        print("\n", .{} );
        
        const results = try solveTestCase(allocator, test_case.n, test_case.values, test_case.queries);
        defer allocator.free(results);
        
        print("Queries and Results:\n", .{});
        for (test_case.queries, 0..) |query, q_idx| {
            const i = query[0];
            const j = query[1];
            const result = results[q_idx];
            const exp = test_case.expected[q_idx];
            
            print("Query: {} {}\n", .{ i, j });
            print("Result: {} (Expected: {})\n", .{ result, exp });
            if (result != exp) {
                print("  WARNING: Result doesn't match expected output\n", .{});
            }
        }
        
        print("\n", .{} );
    }
}
Output:
Test Case 1:
Size: 10, Queries: 3
Values: -1 -1 1 1 1 1 3 10 10 10 
Queries and Results:
Query: 2 3
Result: 1 (Expected: 1)
Query: 1 10
Result: 4 (Expected: 4)
Query: 5 10
Result: 3 (Expected: 3)