Cod sursa(job #3352556)

Utilizator vlad7654vladimir manescu vlad7654 Data 28 aprilie 2026 19:15:47
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.54 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
const int NMAX=2e5;
struct LCT {
    struct node {
        int ch[2], parent, reversed;
    };
    node tree[NMAX+5];
    int get(int x) {
        if (x==tree[tree[x].parent].ch[0]) return 0;
        if (x==tree[tree[x].parent].ch[1]) return 1;
        return -1;
    }
    void push(int x){
        if (tree[x].reversed) {
            swap(tree[x].ch[0] , tree[x].ch[1]);
            tree[tree[x].ch[0]].reversed ^= 1;
            tree[tree[x].ch[1]].reversed ^= 1;
            tree[x].reversed = 0;
        }
    }
    void rotate(int x) {
        int y = tree[x].parent, z=tree[y].parent;//y - parent, z - grandparent
        int side=get(x);
        if (get(y)!=-1) tree[z].ch[get(y)]=x;// move x under z
        tree[x].parent=z;

        tree[y].ch[side]=tree[x].ch[side^1];//move x child to y child
        if (tree[y].ch[side]) tree[tree[y].ch[side]].parent=y;

        tree[x].ch[side^1]=y;//move y under x
        tree[y].parent=x;
    }
    void propagate(int x) {
        if (get(x)!=-1) {
            propagate(tree[x].parent);
        }
        push(x);
    }
    void splay(int x) {
        propagate(x);
        while (get(x)!=-1) {
            int y=tree[x].parent;
            if (get(y)!=-1) {
                int side1=get(y), side2=get(x);
                if (side1==side2) {
                    rotate(y);
                }else {
                    rotate(x);
                }
            }
            rotate(x);
        }
    }
    int access(int x) {
        int last_node=0;
        while (x) {
            splay(x);
            tree[x].ch[1]=last_node;
            last_node=x;
            x=tree[x].parent;
        }
        return last_node;
    }
    int lca(int x, int y) {
        access(x);
        return access(y);
    }
    void make_root(int x) {
        access(x);
        splay(x);
        tree[x].reversed ^= 1;
        push(x);
    }
    int find_root(int x) {
        access(x);
        splay(x);
        while (tree[x].ch[0]) {
            push(x);
            x=tree[x].ch[0];
        }
        splay(x);
        return x;
    }
    void link(int x, int y) { // y parent x child
        make_root(x);
        if (find_root(y)!=x) {
            tree[x].parent=y;
        }
    }
};
LCT lct;
int main() {
    int n, m;
    fin>>n>>m;
    for (int i=2;i<=n;i++) {
        int val;
        fin>>val;
        lct.link(val, i);
    }
    lct.make_root(1);
    for (int i=1;i<=m;i++) {
        int x, y;
        fin>>x>>y;
        fout<<lct.lca(x,y)<<'\n';
    }
}