Pagini recente » Cod sursa (job #863403) | Cod sursa (job #2549797) | Cod sursa (job #1131226) | Cod sursa (job #3263550) | Cod sursa (job #2210194)
#include <vector>
#include <cstdio>
namespace algo {
struct EmptyType {};
// Remember to Init() after adding the edges
template <typename EdgeAttributes = EmptyType>
class Graph {
private:
template <typename T> struct Range;
public:
explicit Graph(int n, 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 AdditionalInit() {}
void Init() {
ReorderEdges();
AdditionalInit();
}
size_t size() const {
return (size_t)n_;
}
Range<int> operator[](const int u) {
return Range<int>(&edges_[offset_[u]], &edges_[offset_[u + 1]]);
}
int node(const int edge_idx) const {
return in_[edge_idx].to;
}
EdgeAttributes value(const int edge_idx) const {
return in_[edge_idx];
}
private:
Graph() = delete;
struct Edge : public EdgeAttributes {
int from, to;
Edge() {}
Edge(int from_, 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;
};
void ReorderEdges() {
edges_.resize(in_.size());
for (auto&& e : in_) {
++offset_[e.from];
}
for (int i = 1; i <= n_; ++i) {
offset_[i] += offset_[i - 1];
}
for (size_t i = 0; i < in_.size(); ++i) {
edges_[--offset_[in_[i].from]] = i;
}
}
int n_;
std::vector<int> offset_, edges_;
std::vector<Edge> in_;
};
} // namespace algo
namespace algo {
template <typename EdgeAttributes=EmptyType>
class Tree : public Graph<EdgeAttributes> {
public:
explicit Tree(int n, int root=0) : Graph<EdgeAttributes>(n, n - 1), root_(root) {}
void AdditionalInit() override {
DepthSearch(root_);
}
int parent(int node) const {
return parent_[node];
}
int preorder(int node) const {
return order_[node];
}
int root() const {
return root_;
}
private:
Tree() = delete;
void DepthSearch(int root) {
parent_.assign(this->size(), -1);
order_.reserve(this->size());
std::vector<int> stk = {root};
while (not stk.empty()) {
int node = stk.back();
order_.push_back(node);
stk.pop_back();
for (auto it : this->operator[](node)) {
int to = this->node(it);
if (parent_[to] == -1 and to != root) {
parent_[to] = node;
stk.push_back(to);
}
}
}
}
std::vector<int> parent_, order_;
int root_;
};
} // namespace algo
namespace algo {
class SchieberVishkinLCA {
public:
template <typename EdgeAttributes>
explicit SchieberVishkinLCA(Tree<EdgeAttributes>& tree)
: idx_(tree.size()),
max_idx_(tree.size()),
ancestor_height_(tree.size()),
path_parent_(tree.size()) {
const int n = tree.size();
for (int i = 0; i < n; ++i) {
idx_[tree.preorder(i)] = i + 1;
}
max_idx_ = idx_;
for (int i = n - 1; i > 0; --i) {
const int node = tree.preorder(i);
if (lsb(max_idx_[tree.parent(node)]) < lsb(max_idx_[node])) {
max_idx_[tree.parent(node)] = max_idx_[node];
}
}
ancestor_height_[tree.root()] = 0;
for (int i = 1; i < n; ++i) {
const int node = tree.preorder(i);
ancestor_height_[node] =
ancestor_height_[tree.parent(node)] | lsb(max_idx_[node]);
}
path_parent_[idx_[tree.root()] - 1] = tree.root();
for (int i = 0; i < n; ++i) {
const int node = tree.preorder(i);
for (auto&& edge : tree[node]) {
const int son = tree.node(edge);
if (tree.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:
SchieberVishkinLCA() = delete;
static int lsb(int value) {
return value & -value;
}
static int msb(int v) {
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return v >> 1;
}
std::vector<int> idx_, max_idx_, ancestor_height_, path_parent_;
};
} // namespace algo
int main()
{
#ifdef INFOARENA
freopen("lca.in", "r", stdin);
freopen("lca.out", "w", stdout);
#endif
int n, q;
scanf("%d%d", &n, &q);
algo::Tree<> tree(n);
for (int i = 1; i < n; ++i) {
int parent;
scanf("%d", &parent);
tree.AddEdge(parent - 1, i);
}
tree.Init();
algo::SchieberVishkinLCA lca(tree);
while (q--> 0) {
int u, v;
scanf("%d%d", &u, &v);
--u; --v;
printf("%d\n", 1 + lca.Query(u, v));
}
return 0;
}