Cod sursa(job #1735463)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 29 iulie 2016 23:15:42
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 5.45 kb
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>

#pragma warning(disable : 4996)

using namespace std;

#define MaxN 100000
#define NIL -1
#define BUFFSIZE (1 << 12)

inline char getChar() {
    static char buf[BUFFSIZE];
    static int pos = BUFFSIZE;
    if (pos == BUFFSIZE) {
        fread_unlocked(buf, 1, BUFFSIZE, stdin);
        pos = 0;
    }
    return buf[pos++];
}

inline int readInt() {
    register unsigned q = 0;
    char c;
    do {
        c = getChar();
    } while (!isdigit(c));
    do {
        q = (q << 1) + (q << 3) + (c - '0');
        c = getChar();
    } while (isdigit(c));
    return q;
}

char bf[BUFFSIZE];
int bfPos;

inline void putChar(const char &ch) {
    bf[bfPos++] = ch;
    if (bfPos == BUFFSIZE) {
        fwrite_unlocked(bf, 1, BUFFSIZE, stdout);
        bfPos = 0;
    }
}

inline void writeInt(int X) {
    char digs[10];
    int n = 0, q;
    do {
        q = X / 10;
        digs[n++] = '0' + X - (q << 1) - (q << 3);
        X = q;
    } while (X);
    while (n--) {
        putChar(digs[n]);
    }
    putChar('\n');
}

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", "r", stdin);
    freopen("lca.out", "w", stdout);

    int N = readInt(), M = readInt();
    for (int i = 1; i < N; i++) {
        int to = readInt() - 1;
        T.Link(to, i);
    }
    T.MakeRoot(0);
    for (int i = 0; i < M; i++) {
        writeInt(1 + T.LCA(readInt() - 1, readInt() - 1));
    }
    fwrite(bf, 1, bfPos, stdout);
    fclose(stdout);
}