Pagini recente » Cod sursa (job #1079523) | Cod sursa (job #2187156) | Cod sursa (job #1523031) | Cod sursa (job #882105) | Cod sursa (job #1735463)
#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);
}