Pagini recente » Cod sursa (job #1393487) | Cod sursa (job #2238172) | Cod sursa (job #1513961) | Cod sursa (job #1802852)
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int NMAX = 100000;
const int BUFFSIZE = 4096;
const int NIL = -1;
inline char GetChar() {
static char buff[BUFFSIZE];
static int pos = BUFFSIZE;
if (pos == BUFFSIZE) {
fread(buff, 1, BUFFSIZE, stdin);
pos = 0;
}
return buff[pos++];
}
inline int ReadInt() {
int q = 0;
char c;
do {
c = GetChar();
} while (not isdigit(c));
do {
q = (q << 1) + (q << 3) + (c - '0');
c = GetChar();
} while (isdigit(c));
return q;
}
int pointer[NMAX - 1];
int head[NMAX];
int idx[NMAX], maxIdx[NMAX];
int ancestorHeights[NMAX];
int pathParent[NMAX];
inline int LSB(const int& x) {
return x & -x;
}
inline int MSB(int x) {
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x >> 1);
}
void BuildSchieberVishkin(const int n) {
static int parent[NMAX], vertices[NMAX];
// dfs
{
int stackSize = 1, currIdx = 1;
while (stackSize) {
const int node = vertices[--stackSize];
idx[node] = currIdx++;
for (int i = head[node]; ~i; i = pointer[i]) {
const int son = i + 1;
parent[son] = node;
vertices[stackSize++] = son;
}
}
}
// bfs
{
int queueFront = 0, queueBack = 1;
vertices[0] = 0;
while (queueBack != queueFront) {
const int node = vertices[queueFront++];
for (int i = head[node]; ~i; i = pointer[i]) {
const int son = i + 1;
vertices[queueBack++] = son;
}
}
}
memcpy(maxIdx, idx, 4 * n);
for (int i = n - 1; i >= 0; i -= 1) {
const int node = vertices[i];
if (LSB(maxIdx[parent[node]]) < LSB(maxIdx[node])) {
maxIdx[parent[node]] = maxIdx[node];
}
}
ancestorHeights[0] = 0;
for (int i = 0; i < n; i += 1) {
ancestorHeights[vertices[i]] = ancestorHeights[parent[vertices[i]]] | LSB(maxIdx[vertices[i]]);
}
memcpy(pathParent, parent, 4 * n);
pathParent[idx[0] - 1] = 0;
for (int i = 0; i < n; i += 1) {
const int node = vertices[i];
for (int j = head[node]; ~j; j = pointer[j]) {
const int son = j + 1;
if (maxIdx[node] != maxIdx[son]) {
pathParent[idx[son] - 1] = node;
} else {
pathParent[idx[son] - 1] = pathParent[idx[node] - 1];
}
}
}
}
int Query(const int& x, const int& y) {
const int Ix = maxIdx[x], Iy = maxIdx[y];
const int hIx = LSB(Ix), hIy = LSB(Iy);
const int msbMask = MSB((Ix ^ Iy) | hIx | hIy);
const int mask = LSB(ancestorHeights[x] & ancestorHeights[y] & ~msbMask);
int left, right;
if (mask == hIx) {
left = x;
} else {
const int kMask = MSB(ancestorHeights[x] & (mask - 1));
left = pathParent[(idx[x] & ~kMask | (kMask + 1)) - 1];
}
if (mask == hIy) {
right = y;
} else {
const int kMask = MSB(ancestorHeights[y] & (mask - 1));
right = pathParent[(idx[y] & ~kMask | (kMask + 1)) - 1];
}
return idx[left] < idx[right] ? left : right;
}
int main() {
freopen("lca.in", "r", stdin);
freopen("lca.out", "w", stdout);
int n = ReadInt(), m = ReadInt();
memset(head, NIL, 4 * n);
for (int i = 1; i < n; i += 1) {
const int x = ReadInt() - 1;
pointer[i - 1] = head[x];
head[x] = i - 1;
}
BuildSchieberVishkin(n);
while (m--) {
printf("%d\n", 1 + Query(ReadInt() - 1, ReadInt() - 1));
}
return 0;
}