Poklon ⧉
poklon.cpp
poklon.py
_179//_179// Created by Gaelan McMillan on 2022-09-10._179//_179_179#ifndef MORE_GENERIC_PATIENCE_H_179#define MORE_GENERIC_PATIENCE_H_179_179/* * * * * * *\_179 * Objective:_179 * Sort a std::container of elements to find the longest chain,_179 * given a comparator describing some partial order._179 *_179 * Return value could be a few things. Some problems only need to know the number of elements_179 * in the longest chain. (The Longest Monotone Subsequence problem)_179 *_179 * Some variations ask for the subsequence itself. In this case, having patience return a lazy-convertible struct_179 * (essentially a wrapper around the subsequence tail) could be ideal._179 *_179 * Let's explore how we want the API to behave._179 * In the case of "Poklon":_179 *_179 * ```_179 * struct interval { int low, high; };_179 * std::vector<interval> intervals {...};_179 * sort(intervals.begin(), intervals.end(), preprocess);_179 * auto LIS = patience(intervals.begin(), intervals.end(), comparator);_179 * for (auto& element : LIS)_179 * {_179 * std::cout << element.low << ' ' << element.high << '\n';_179 * }_179 * ```_179 *_179 * In the case of "Russian Doll Envelopes"_179 *_179 * ```_179 * sort(envelopes.begin(), envelopes.end(), preprocess);_179 * auto LIS = patience(envelopes.begin(), envelopes.end(), comparator);_179 * return LIS.size();_179 * ```_179 *_179 * Currently passing longest-monotone-subsequence tests._179 * Non-monotone tests are more subtle._179 * */_179#include <vector>_179#include <algorithm>_179#include <numeric>_179#include <iostream>_179_179template<class InputIterator, class Comparator, class BiPred>_179auto __patience (InputIterator begin, InputIterator end, Comparator pre, BiPred pred)_179{_179 using T = typename std::iterator_traits<InputIterator>::value_type;_179_179 if constexpr(not std::is_same_v<Comparator, std::nullptr_t>)_179 std::sort(begin, end, pre);_179_179 struct node_179 {_179 T item;_179 node* next;_179 node() = default;_179 node(T t, node* p) : item(t), next(p) {}_179 };_179_179 auto node_pred = [&pred] (node* a, node* b)_179 {_179 return pred(a->item, b->item);_179 };_179_179 const auto dist = std::distance(begin, end);_179 node* nodes = new node[dist];_179_179 std::vector<node*> piles;_179_179 for (; begin != end; ++begin)_179 {_179 node* wrapped = new (nodes++) node(*begin, nullptr);_179 if (piles.empty())_179 {_179 piles.push_back(wrapped);_179 continue;_179 }_179_179 auto lb = std::lower_bound(piles.begin(), piles.end(), wrapped, node_pred);_179_179 if (lb == piles.begin()) // new first pile_179 {_179 *lb = wrapped;_179 }_179 else if (lb == piles.end())_179 {_179 wrapped->next = piles.back();_179 piles.push_back(wrapped);_179 }_179 else_179 {_179 wrapped->next = *(lb-1);_179 *lb = wrapped;_179 }_179_179 }_179_179 std::vector<T> seq;_179 node* cur = piles.back();_179_179 while (cur != nullptr)_179 {_179 seq.push_back(cur->item);_179 cur = cur->next;_179 }_179_179 std::reverse(seq.begin(), seq.end());_179 return seq;_179}_179_179template <class II>_179auto patience(II begin, II end)_179{_179 using T = typename std::iterator_traits<II>::value_type;_179 return __patience(begin, end, nullptr, std::less<T>());_179}_179_179template <class II, class Comparator, class BiPred>_179auto patience(II begin, II end, Comparator pre, BiPred pred)_179{_179 return __patience(begin, end, pre, pred);_179}_179_179/*_179 * Maybe returning a convertible struct would be a nice API._179 *_179 * auto p = make_patience(vec.begin(), vec.end())_179 * .with_preprocess() // argument can be a comparator — std::less<> by default_179 * .non_monotone()_179 * */_179#endif //MORE_GENERIC_PATIENCE_H_179_179_179using namespace std;_179_179int main() _179{_179 struct interval _179 {_179 int low;_179 int high;_179 };_179 _179 int n;_179 cin >> n;_179 vector<interval> intervals (n);_179 for (interval& i : intervals) _179 {_179 cin >> i.low >> i.high;_179 }_179 _179 auto preprocess = [](const interval& a, const interval& b) {_179 if (a.low == b.low)_179 return a.high > b.high;_179 return a.low < b.low;_179 };_179_179 auto pred = [](const interval& a, const interval& b) {_179 return a.high >= b.high;_179 };_179_179 auto LIS = patience (_179 intervals.begin(),_179 intervals.end(),_179 preprocess,_179 pred_179 );_179_179 cout << LIS.size() << '\n';_179 for (auto e : LIS)_179 std::cout << e.low << ' ' << e.high << '\n';_179 _179 return 0;_179}
If you found this solution helpful, consider leaving a star!