Cod sursa(job #1735461)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 29 iulie 2016 23:09:21
Problema Lowest Common Ancestor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 4.49 kb
#include <cstdio>
#include <algorithm>
#include <cstring>

#pragma warning(disable : 4996)

using namespace std;

#define MaxN 100000
#define NIL -1

struct LinkCutTree { 
	int left[MaxN], right[MaxN], parent[MaxN];
	int cost[MaxN], delta[MaxN];
	bool revert[MaxN];

    LinkCutTree() {
        memset(left, NIL, 4 * MaxN);
        memset(right, NIL, 4 * MaxN);
        memset(parent, NIL, 4 * MaxN);
    }

	void Lazy(const int node) {
		if (revert[node]) {
			revert[node] = false;
			swap(left[node], right[node]);
			if (left[node] != NIL) {
				revert[left[node]] ^= 1;
			}
			if (right[node] != NIL) {
				revert[right[node]] ^= 1;
			}
		}
	}

	void Update(const int node) {
		delta[node] = cost[node];
		if ((left[node] != NIL) && (delta[node] < delta[left[node]])) {
			delta[node] = delta[left[node]];
		}
		if ((right[node] != NIL) && (delta[node] < delta[right[node]])) {
			delta[node] = delta[right[node]];
		}
	}

	bool isRoot(const int node) {
		return parent[node] == NIL
			|| (left[parent[node]] != node && right[parent[node]] != node);
	}

	void Zig(const int node) {
		const int q = parent[node];
		const int t = parent[q];
		left[q] = right[node];
		if (left[q] != NIL) {
			parent[left[q]] = q;
		}
		right[node] = q;
		parent[q] = node;
		parent[node] = t;
		if (parent[node] != NIL) {
			if (left[t] == q) {
				left[t] = node;
			} else if (right[t] == q) {
				right[t] = node;
			}
		}
		Update(q);
	}

	void Zag(const int node) {
		const int q = parent[node];
		const int t = parent[q];
		right[q] = left[node];
		if (right[q] != NIL) {
			parent[right[q]] = q;
		}
		left[node] = q;
		parent[q] = node;
		parent[node] = t;
		if (parent[node] != NIL) {
			if (left[t] == q) {
				left[t] = node;
			} else if (right[t] == q) {
				right[t] = node;
			}
		}
		Update(q);
	}

	void Splay(const int node) {
		while (!isRoot(node)) {
			const int q = parent[node];
			const int t = parent[q];
			if (isRoot(q)) {
				Lazy(q);
				Lazy(node);
				if (left[q] == node) {
					Zig(node);
				} else {
					Zag(node);
				}
            } else {
                Lazy(t);
                Lazy(q);
                Lazy(node);
                if ((node == left[q]) == (q == left[t])) {
                    if (node == left[q]) {
                        Zig(q);
                        Zig(node);
                    } else {
                        Zag(q);
                        Zag(node);
                    }
                } else {
                    if (node == left[q]) {
                        Zig(node);
                    } else {
                        Zag(node);
                    }
                    if (node == left[t]) {
                        Zig(node);
                    } else {
                        Zag(node);
                    }
                }
            }
		}
        Lazy(node);
        Update(node);
	}

    int Expose(const int node) {
        int to = NIL;
        for (int i = node; i != NIL; i = parent[i]) {
            Splay(i);
            left[i] = to;
            to = i;
        }
        Splay(node);
        return to;
    }

    void MakeRoot(const int node) {
        Expose(node);
        revert[node] ^= 1;
    }

    bool ConnectedNodes(const int u, const int v) {
        if (u != v) {
            Expose(u);
            Expose(v);
            return parent[u] != NIL;
        }
        return true;
    }

    int LCA(const int u, const int v) {
        Expose(u);
        return Expose(v);
    }

    void Link(const int u, const int v) {
        MakeRoot(u);
        parent[u] = v;
    }

    void Cut(const int u, const int v) {
        MakeRoot(u);
        Expose(v);
        parent[right[v]] = NIL;
        right[v] = NIL;
    }

    int QueryPath(const int u, const int v) {
        MakeRoot(u);
        Expose(v);
        return delta[v];
    }

    void UpdatePath(const int u, const int v, const int key) {
        MakeRoot(u);
        Expose(v);
        cost[v] = delta[v] = key;
    }
} T;

int main() {
    freopen("lca.in", "rb", stdin);
    freopen("lca.out", "wb", stdout);

    int N, M;
    scanf("%d %d", &N, &M);
    for (int i = 1; i < N; i++) {
        int to;
        scanf("%d", &to);
        T.Link(to - 1, i);
    }
    T.MakeRoot(0);
    for (int i = 0; i < M; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        printf("%d\n", 1 + T.LCA(u - 1, v - 1));
    }
	return 0;
}