Pagini recente » Cod sursa (job #1628217) | Cod sursa (job #1154) | Cod sursa (job #1683875) | Cod sursa (job #1882756) | Cod sursa (job #2386783)
// https://www.infoarena.ro/problema/stramosi
#ifdef __GNUC__
#define NDEBUG
#endif
#include <algorithm>
#include <cassert>
#include <fstream>
#include <functional>
#include <iostream>
#include <stack>
#include <unordered_map>
#include <vector>
constexpr const char newl = '\n';
class Bool
{
private:
bool value_;
public:
Bool() : value_{} {}
Bool(bool value) : value_{value} {}
operator bool() const { return value_; }
};
struct Question
{
int person_id;
int ancestor_level;
int ancestor_id;
};
auto test() { Bool b = true; }
struct Problem
{
int N, M;
std::vector<int> parents;
std::vector<std::vector<int>> children;
std::vector<Question> questions;
std::unordered_map<int, std::reference_wrapper<Question>> questions_by_person;
auto read_input()
{
std::ifstream in{"stramosi.in"};
assert(in);
in >> N >> M;
assert(in);
parents.resize(N + 1);
children.resize(N + 1);
parents[0] = 0;
// read parents
for (int person_id = 1; person_id < static_cast<int>(parents.size()); ++person_id)
{
int parent_id;
in >> parent_id;
assert(in);
parents[person_id] = parent_id;
children[parent_id].push_back(person_id);
}
questions.resize(M);
// read questions
for (Question& question : questions)
{
in >> question.person_id >> question.ancestor_level;
assert(in);
questions_by_person.insert({question.person_id, question});
}
}
auto solve_impl()
{
int level = 0;
std::vector<Bool> visited(parents.size(), false);
std::stack<int> frontier;
std::vector<int> path;
path.reserve(N >> 1);
frontier.push(0);
while (!frontier.empty())
{
// select a node from frontier
int selected_person_id = frontier.top();
frontier.pop();
// remove and add to path
auto parent_of_selected_it =
std::find(path.rbegin(), path.rend(), parents[selected_person_id]);
if (parent_of_selected_it != path.rend() &&
(parent_of_selected_it + 1).base() != path.end() &&
(parent_of_selected_it + 1).base() + 1 != path.end())
{
path.erase((parent_of_selected_it + 1).base() + 1, path.end());
}
path.push_back(selected_person_id);
// check for a question
auto it = questions_by_person.find(selected_person_id);
if (it != questions_by_person.end())
{
Question& question = it->second;
int path_idx = static_cast<int>(path.size() - 1 - question.ancestor_level);
if (path_idx <= 0)
question.ancestor_id = 0;
else
question.ancestor_id = path[path_idx];
}
// expand frontier with children
for (int& child : children[selected_person_id])
{
frontier.push(child);
}
}
}
auto write_out()
{
std::ofstream out{"stramosi.out"};
assert(out);
for (auto& question : questions)
{
out << question.ancestor_id << newl;
assert(out);
}
}
auto solve()
{
read_input();
solve_impl();
write_out();
}
};
int main()
{
Problem problem;
problem.solve();
}