Pagini recente » Cod sursa (job #2974244) | Cod sursa (job #2262726) | Contact | Cod sursa (job #301616) | Cod sursa (job #1559926)
#include <cstdio>
#include <cstring>
#include <vector>
#include <cctype>
#include <algorithm>
using namespace std;
const int maxN = 100000;
const int maxNd = maxN << 1;
const int maxSize = 1 << 20;
class ReadStream {
private:
int cursor;
char buf[maxSize];
FILE *f;
inline void move() {
++ cursor;
if(cursor == maxSize) {
cursor = 0;
fread(buf, maxSize, 1, f);
}
}
inline int todig(char c) {
return c - '0';
}
public:
ReadStream() {}
ReadStream(const char *fname) {
f = fopen(fname, "r");
cursor = 0;
fread(buf, maxSize, 1, f);
}
ReadStream &operator >> (int& N) {
char sign = '+';
while(!isdigit(buf[cursor])) {
sign = buf[cursor];
move();
}
N = 0;
while(isdigit(buf[cursor])) {
N = N * 10 + todig(buf[cursor]);
move();
}
if(sign == '-')
N = -N;
return *this;
}
ReadStream &operator >> (float& N) {
char sign = '+';
while(!isdigit(buf[cursor])) {
sign = buf[cursor];
move();
}
N = 0;
while(isdigit(buf[cursor])) {
N = N * 10 + todig(buf[cursor]);
move();
}
if(buf[cursor] == '.') {
float p = 0.1;
move();
while(isdigit(buf[cursor])) {
N = N + p * todig(buf[cursor]);
p *= 0.1;
move();
}
}
if(sign == '-')
N = -N;
return *this;
}
void close() {
fclose(f);
}
};
class WriteStream {
private:
FILE* stream;
int pos;
char buffer[maxSize];
void dump() {
if (pos > maxSize) {
fwrite(buffer, sizeof(char), pos, stream);
pos = 0;
}
}
public:
WriteStream(FILE* stream) {
this->stream = stream;
this->pos = 0;
}
WriteStream(const char *fname) {
this->stream = fopen(fname, "w");
this->pos = 0;
}
WriteStream& operator << (unsigned int value) {
if (value == 0) {
buffer[pos] = '0';
pos++;
} else {
int newPos = pos;
while(value > 0) {
buffer[newPos] = '0' + (value % 10);
newPos++;
value /= 10;
}
std::reverse(buffer + pos, buffer + newPos);
pos = newPos;
}
dump();
return *this;
}
WriteStream& operator << (char value) {
buffer[pos] = value;
pos++;
dump();
return *this;
}
WriteStream& operator << (int value) {
if(value == 0) {
buffer[pos ++] = '0';
dump();
return *this;
}
if(value < 0)
buffer[pos ++] = '-', value = -value;
int newPos = pos;
while(value > 0) {
buffer[newPos ++] = '0' + (value % 10);
value /= 10;
}
std::reverse(buffer + pos, buffer + newPos);
pos = newPos;
dump();
return *this;
}
~WriteStream() {
fwrite(buffer, sizeof(char), pos, stream);
}
void close() {
pos = maxSize + 1;
dump();
fclose(stream);
}
};
int N;
bool viz[1 + maxN];
vector<int> sons[1 + maxN];
int id[1 + maxN], ac;
int euler[maxNd], where[1 + maxN], e;
int rmq[20][maxNd << 1];
int Log[maxNd + 1];
void rmqCompute(int v[], int N) {
for(int i = 0; i < N; ++ i)
rmq[0][i] = v[i];
for(int i = 1; (1 << i) <= N; ++ i)
Log[(1 << i)] = 1;
for(int i = 1; i <= N; ++ i)
Log[i] += Log[i - 1];
int p = 2;
for(int step = 1; p <= N; ++ step, p <<= 1) {
int put = p >> 1;
for(int i = 0; i + put < N; ++ i)
rmq[step][i] = min(rmq[step - 1][i], rmq[step - 1][i + put]);
}
}
int rmQuery(int x, int y) {
int l = y - x + 1;
int step = Log[l];
return min(rmq[step][x], rmq[step][y - (1 << step) + 1]);
}
void dfs(int node = 1) {
if(!viz[node]) {
viz[node] = true;
int nodeAc = ac;
id[ac ++] = node;
where[node] = e;
euler[e ++] = nodeAc;
for (int son: sons[node]) {
dfs(son);
euler[e ++] = nodeAc;
}
}
}
int lca(int x, int y) {
x = where[x];
y = where[y];
return id[rmQuery(min(x, y), max(x, y))];
}
int main() {
ReadStream in("lca.in");
WriteStream out("lca.out");
int M;
in >> N >> M;
for(int i = 2; i <= N; ++ i) {
int fatherI;
in >> fatherI;
sons[fatherI].push_back(i);
}
dfs();
rmqCompute(euler, e);
while(M --) {
int x, y;
in >> x >> y;
out << lca(x, y) << '\n';
}
in.close();
out.close();
return 0;
}