Pagini recente » Cod sursa (job #914514) | Cod sursa (job #841253) | Cod sursa (job #2054367)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <vector>
#include <fstream>
#include <memory>
using namespace std;
class Reader {
public:
Reader(const string& filename):
m_stream(filename),
m_pos(kBufferSize - 1),
m_buffer(new char[kBufferSize]) {
next();
}
Reader& operator>>(int& value) {
value = 0;
while (current() < '0' || current() > '9')
next();
while (current() >= '0' && current() <= '9') {
value = value * 10 + current() - '0';
next();
}
return *this;
}
private:
const int kBufferSize = 32768;
char current() {
return m_buffer[m_pos];
}
void next() {
if (!(++m_pos != kBufferSize)) {
m_stream.read(m_buffer.get(), kBufferSize);
m_pos = 0;
}
}
ifstream m_stream;
int m_pos;
unique_ptr<char[]> m_buffer;
};
class Graph {
private:
struct Edge {
int from, to;
Edge() { }
Edge(const int _from, const int _to) : from(_from), to(_to) { }
};
template<typename T>
struct Range {
struct Iterator {
T& operator *() const { return *iter; }
bool operator !=(const Iterator& rhs) const { return iter != rhs.iter; }
void operator ++() { ++iter; }
T* operator +(int i) const { return iter + i; }
size_t operator -(const Iterator& rhs) const { return iter - rhs.iter; }
T* iter;
};
Range(T* _first, T* _last) : first({_first}), last({_last}) { }
T operator[] (const int i) { return *(first + i); }
size_t size() const { return last - first; }
Iterator& begin() { return first; }
Iterator& end() { return last; }
Iterator first, last;
};
public:
Range<int> operator [](int u) {
return Range<int>(&edges[offset[u]], &edges[offset[u + 1]]);
}
Graph() = default;
Graph(const int N, const int M=0) : n(N), offset(N + 1) {
if (M > 0) { in.reserve(M); }
}
void AddEdge(int x, int y) { in.emplace_back(x, y); }
void Init() {
edges.resize(in.size());
for (auto&& e : in) { offset[e.from] += 1; }
for (int i = 1; i <= n; i += 1) {
offset[i] += offset[i - 1];
}
for (auto&& e : in) {
edges[--offset[e.from]] = e.to;
}
in.clear();
}
size_t size() const {
return (size_t)n;
}
private:
int n;
vector<int> offset, edges;
vector<Edge> in;
};
class SchieberVishkinLCA {
private:
static inline int lsb(int value) {
return value & -value;
}
static inline int msb(int v) {
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return v >> 1;
}
public:
SchieberVishkinLCA() = default;
SchieberVishkinLCA(Graph& G, int root) : idx(G.size()), max_idx(G.size()), ancestor_height(G.size()), path_parent(G.size()) {
int n = G.size();
vector<int> parent(n), vertices(n);
auto Dfs = [&]() {
int stack_size = 1, euler_idx = 1;
vertices[0] = root;
parent[root] = -1;
while (stack_size > 0) {
const int node = vertices[--stack_size];
idx[node] = euler_idx++;
for (auto&& son : G[node]) {
if (parent[node] != son) {
parent[son] = node;
vertices[stack_size++] = son;
}
}
}
};
auto Bfs = [&]() {
int q_front = 0, q_end = 1;
vertices[0] = root;
parent[root] = -1;
while (q_front != q_end) {
const int node = vertices[q_front++];
for (auto&& son : G[node]) {
if (parent[node] != son) {
parent[son] = node;
vertices[q_end++] = son;
}
}
}
};
Dfs(); Bfs();
max_idx = idx;
for (int i = n - 1; i > 0; i -= 1) {
const int node = vertices[i];
if (lsb(max_idx[parent[node]]) < lsb(max_idx[node])) {
max_idx[parent[node]] = max_idx[node];
}
}
ancestor_height[root] = 0;
for (int i = 1; i < n; i += 1) {
const int node = vertices[i];
ancestor_height[node] = ancestor_height[parent[node]] | lsb(max_idx[node]);
}
path_parent[idx[root] - 1] = root;
for (int i = 0; i < n; i += 1) {
const int node = vertices[i];
for (auto&& son : G[node]) {
if (parent[node] == son) {
continue;
}
path_parent[idx[son] - 1] = (max_idx[node] == max_idx[son]) ? path_parent[idx[node] - 1] : node;
}
}
}
int Query(int x, int y) const {
const int Ix = max_idx[x], Iy = max_idx[y];
const int hIx = lsb(Ix), hIy = lsb(Iy);
const int msb_mask = msb((Ix ^ Iy) | hIx | hIy);
const int mask = lsb(ancestor_height[x] & ancestor_height[y] & ~msb_mask);
int left, right;
if (mask == hIx) {
left = x;
} else {
const int kMask = msb(ancestor_height[x] & (mask - 1));
left = path_parent[((idx[x] & ~kMask) | (kMask + 1)) - 1];
}
if (mask == hIy) {
right = y;
} else {
const int kMask = msb(ancestor_height[y] & (mask - 1));
right = path_parent[((idx[y] & ~kMask) | (kMask + 1)) - 1];
}
return (idx[left] < idx[right]) ? left : right;
}
private:
vector<int> idx, max_idx, ancestor_height, path_parent;
};
int main() {
Reader r("lca.in");
ofstream cout("lca.out");
int n, m; r >> n >> m;
Graph G(n, n - 1);
for (int i = 1; i < n; i += 1) {
int parent; r >> parent; parent -= 1;
G.AddEdge(parent, i);
}
G.Init();
SchieberVishkinLCA LcaSolver(G, 0);
for (int i = 0; i < m; i += 1) {
int x, y; r >> x >> y; x -= 1; y -= 1;
cout << 1 + LcaSolver.Query(x, y) << '\n';
}
}