Pagini recente » Cod sursa (job #884093) | Cod sursa (job #1536060) | Cod sursa (job #987396) | Cod sursa (job #2848891) | Cod sursa (job #2071767)
#include <fstream>
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
struct EmptyType {};
// Remember to Init() after adding the edges
template<typename EdgeAttributes = EmptyType>
class Graph {
private:
Graph();
struct Edge : private EdgeAttributes {
int from, to;
Edge() { }
Edge(const int _from, const int _to, const EdgeAttributes& attr) : EdgeAttributes(attr), 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:
explicit 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, const EdgeAttributes attr = EdgeAttributes()) { in_.emplace_back(x, y, attr); }
virtual void Init() {
ReorderEdges();
}
size_t size() const {
return (size_t)n_;
}
Range<int> operator [](const int u) {
return Range<int>(&edges_[offset_[u]], &edges_[offset_[u + 1]]);
}
protected:
void ReorderEdges() {
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();
}
int n_;
vector<int> offset_, edges_;
vector<Edge> in_;
};
template<typename EdgeAttributes = EmptyType>
class Tree : public Graph<EdgeAttributes> {
private:
Tree() { }
public:
explicit Tree(int N) : Graph<EdgeAttributes>(N, N - 1) { }
virtual void Init(const int root=0) {
this->ReorderEdges();
Dfs(root);
}
int parent(const int node) const {
return parent_[node];
}
int preorder(const int idx) const {
return preorder_[idx];
}
private:
void Dfs(const int root) {
parent_.assign(this->n_, -1);
vector<int> stk;
stk.push_back(root);
while (not stk.empty()) {
const int node = stk.back();
stk.pop_back();
preorder_.push_back(node);
for (auto&& son : (*this)[node]) {
if (parent_[son] == -1) {
parent_[son] = node;
stk.push_back(son);
}
}
}
}
vector<int> parent_, preorder_;
};
class SchieberVishkinLCA {
private:
SchieberVishkinLCA();
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:
template<typename EdgeAttributes>
explicit SchieberVishkinLCA(Tree<EdgeAttributes>& G, int root = 0) : idx_(G.size()), max_idx_(G.size()), ancestor_height_(G.size()), path_parent_(G.size()) {
const int n = G.size();
for (int i = 0; i < n; i += 1) {
idx_[G.preorder(i)] = i + 1;
}
max_idx_ = idx_;
for (int i = n - 1; i > 0; i -= 1) {
const int node = G.preorder(i);
if (lsb(max_idx_[G.parent(node)]) < lsb(max_idx_[node])) {
max_idx_[G.parent(node)] = max_idx_[node];
}
}
ancestor_height_[root] = 0;
for (int i = 1; i < n; i += 1) {
const int node = G.preorder(i);
ancestor_height_[node] = ancestor_height_[G.parent(node)] | lsb(max_idx_[node]);
}
path_parent_[idx_[root] - 1] = root;
for (int i = 0; i < n; i += 1) {
const int node = G.preorder(i);
for (auto&& son : G[node]) {
if (G.parent(node) == son) {
continue;
}
path_parent_[idx_[son] - 1] = (max_idx_[node] == max_idx_[son]) ? path_parent_[idx_[node] - 1] : node;
}
}
}
int Query(const int x, const int y) const {
const int ix = max_idx_[x], iy = max_idx_[y];
const int h_ix = lsb(ix), h_iy = lsb(iy);
const int msb_mask = msb((ix ^ iy) | h_ix | h_iy);
const int mask = lsb(ancestor_height_[x] & ancestor_height_[y] & ~msb_mask);
const int msb_x = msb(ancestor_height_[x] & (mask - 1));
const int msb_y = msb(ancestor_height_[y] & (mask - 1));
const int lhs = (mask == h_ix) ? x : path_parent_[((idx_[x] & ~msb_x) | (msb_x + 1)) - 1];
const int rhs = (mask == h_iy) ? y : path_parent_[((idx_[y] & ~msb_y) | (msb_y + 1)) - 1];
return (idx_[lhs] < idx_[rhs]) ? lhs : rhs;
}
private:
vector<int> idx_, max_idx_, ancestor_height_, path_parent_;
};
int main() {
#ifdef INFOARENA
ifstream cin("lca.in");
ofstream cout("lca.out");
#endif
int n, q; cin >> n >> q;
Tree<> tree(n);
for (int i = 1; i < n; i += 1) {
int parent; cin >> parent;
tree.AddEdge(parent - 1, i);
}
tree.Init();
SchieberVishkinLCA lca_solver(tree);
while (q--) {
int x, y; cin >> x >> y; x -= 1; y -= 1;
cout << 1+lca_solver.Query(x, y) << '\n';
}
}