Pagini recente » Cod sursa (job #1293365) | Cod sursa (job #1875008) | Cod sursa (job #1738354) | Cod sursa (job #1556552) | Cod sursa (job #1554930)
/* Bălan Mihail
* http://www.infoarena.ro/problema/stramosi
*/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <utility>
#include <vector>
#include <algorithm>
#include <string>
#include <tuple>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
namespace bolov {
namespace utils {
// inserts val into the sorted container, maintaining the sorted property
template <class Container, class Compare>
static auto insert_sorted(Container &container,
typename Container::value_type const &val,
Compare &&comp) -> void {
container.insert(std::upper_bound(std::begin(container), std::end(container),
val, std::forward<Compare>(comp)),
val);
}
} // ns utils
namespace stramos {
struct Question {
int order;
int member;
int ancestor_distance;
int ancestor;
};
static auto read(std::string const &file_name)
-> std::tuple<std::vector<int>, std::vector<Question>> {
std::fstream ifs{file_name};
if (!ifs) {
throw std::runtime_error{"unable to open file"};
}
auto num_members = int{}, num_questions = int{};
ifs >> num_members >> num_questions;
auto parents = std::vector<int>{0};
parents.reserve(num_members + 1);
for (auto i = 1; i <= num_members; ++i) {
auto ancestor = int{};
ifs >> ancestor;
parents.push_back(ancestor);
}
auto questions = std::vector<Question>{};
questions.reserve(num_questions);
for (auto i = 0; i < num_questions; ++i) {
auto member = int{};
auto order = int{};
ifs >> member >> order;
// keep sorted by distance first and then by member
utils::insert_sorted(questions, {i, member, order, -1},
[](Question const &lhs, Question const &rhs) -> bool {
return lhs.ancestor_distance < rhs.ancestor_distance ||
(lhs.ancestor_distance == rhs.ancestor_distance &&
lhs.member < rhs.member);
});
}
return std::make_tuple(std::move(parents), std::move(questions));
}
static auto write(std::string const &file_name,
std::vector<Question> &questions) -> void {
// sort by orginal order
std::sort(std::begin(questions), std::end(questions),
[](bolov::stramos::Question const &lhs,
bolov::stramos::Question const &rhs) {
return lhs.order < rhs.order;
});
std::ofstream ofs{file_name};
for (auto const &question : questions) {
ofs << question.ancestor << endl;
}
}
using question_iterator = typename std::vector<Question>::iterator;
// answers all questions with <distance>
// ancestors contains ancestors of distance <distance>
static auto answer_and_advance_question_it(std::vector<int> const &ancestors,
int distance,
question_iterator &first,
question_iterator last) -> bool {
for (; first != last && first->ancestor_distance == distance; ++first) {
first->ancestor = ancestors[first->member];
}
return first != last;
}
static auto compute_next_distance(std::vector<int> const &parents,
std::vector<int> &ancestors) -> void {
auto size = static_cast<int>(parents.size());
for (auto i = 1; i < size; ++i) {
ancestors[i] = parents[ancestors[i]];
}
}
static auto answer(std::vector<int> &parents,
std::vector<Question> &questions) -> void {
auto question_it = std::begin(questions);
auto const question_last = std::end(questions);
auto ancestors = parents;
for (auto distance = 1;; ++distance) {
if (!answer_and_advance_question_it(ancestors, distance, question_it,
question_last))
return;
compute_next_distance(parents, ancestors);
}
}
} // ns stramos
} // ns bolov
auto main() -> int {
std::ifstream ifs{"stramosi.in"};
if (!ifs) {
throw std::runtime_error{"unable to open file"};
}
std::ofstream ofs{"stramosi.out"};
ofs << 0 << endl;
return 0;
auto parents = std::vector<int>{};
auto questions = std::vector<bolov::stramos::Question>{};
std::tie(parents, questions) = bolov::stramos::read("stramosi.in");
bolov::stramos::answer(parents, questions);
bolov::stramos::write("stramosi.out", questions);
return 0;
}