Pagini recente » Cod sursa (job #2364329) | Cod sursa (job #2364273) | Cod sursa (job #2368349) | Cod sursa (job #1889657) | Cod sursa (job #1735461)
#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;
}