Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <functional>
- #include <iostream>
- #include <list>
- #include <memory>
- #include <stdexcept>
- #include <vector>
- #include <utility>
- template <class T, class Compare = std::less<T>>
- class Heap {
- public:
- using IndexChangeObserver =
- std::function<void(const T& element, size_t new_element_index)>;
- static constexpr size_t k_null_index = static_cast<size_t>(-1);
- explicit Heap(
- Compare compare = Compare(),
- IndexChangeObserver index_change_observer = IndexChangeObserver()) {
- compare_ = compare;
- index_change_observer_ = index_change_observer;
- }
- size_t push(const T& value) {
- elements_.push_back(value);
- NotifyIndexChange(value, size() - 1);
- return SiftUp(elements_.size() - 1);
- }
- void erase(size_t index) {
- elements_[index] = elements_[0];
- NotifyIndexChange(elements_[index], index);
- SiftUp(index);
- pop();
- }
- const T& top() const {
- return elements_[0];
- }
- void pop() {
- NotifyIndexChange(elements_[0], k_null_index);
- if (size() > 1) {
- elements_[0] = elements_[size() - 1];
- NotifyIndexChange(elements_[0], 0);
- }
- elements_.pop_back();
- SiftDown(0);
- }
- size_t size() const {
- return elements_.size();
- }
- bool empty() const {
- return elements_.empty();
- }
- private:
- IndexChangeObserver index_change_observer_;
- Compare compare_;
- std::vector<T> elements_;
- size_t Parent(size_t index) const {
- if (index != 0)
- return (index - 1) / 2;
- return k_null_index;
- }
- size_t LeftSon(size_t index) const {
- if (2 * index + 1 < size())
- return 2 * index + 1;
- return k_null_index;
- }
- size_t RightSon(size_t index) const {
- if (2 * index + 2 < size())
- return 2 * index + 2;
- return k_null_index;
- }
- bool CompareElements(size_t first_index, size_t second_index) const {
- return compare_(elements_[first_index], elements_[second_index]);
- }
- void NotifyIndexChange(const T& element, size_t new_element_index) {
- index_change_observer_(element, new_element_index);
- }
- void SwapElements(size_t first_index, size_t second_index) {
- NotifyIndexChange(elements_[first_index], second_index);
- NotifyIndexChange(elements_[second_index], first_index);
- std::swap(elements_[first_index], elements_[second_index]);
- }
- size_t SiftUp(size_t index) {
- bool tr = true;
- while (tr) {
- size_t parent = Parent(index);
- if (parent == k_null_index)
- break;
- if (CompareElements(index, parent))
- SwapElements(index, parent);
- index = parent;
- }
- return index;
- }
- void SiftDown(size_t index) {
- bool tr = true;
- while (tr) {
- size_t left = LeftSon(index);
- size_t right = RightSon(index);
- size_t swap;
- if (left == k_null_index && right == k_null_index)
- break;
- else if (left == k_null_index && right != k_null_index)
- swap = right;
- else if (left != k_null_index && right == k_null_index)
- swap = left;
- else if (CompareElements(left, right))
- swap = left;
- else
- swap = right;
- if (!CompareElements(index, swap))
- SwapElements(index, swap);
- index = swap;
- }
- }
- };
- struct MemorySegment {
- int left;
- int right;
- size_t heap_index;
- MemorySegment(int left, int right) {
- this->left = left;
- this->right = right;
- }
- size_t Size() const {
- return right - left + 1;
- }
- MemorySegment Unite(const MemorySegment& other) const {
- return MemorySegment(std::min(left, other.left), std::max(right, other.right));
- }
- };
- using MemorySegmentIterator = std::list<MemorySegment>::iterator;
- using MemorySegmentConstIterator = std::list<MemorySegment>::const_iterator;
- struct MemorySegmentSizeCompare {
- bool operator() (MemorySegmentIterator first, MemorySegmentIterator second) const {
- if ((*first).Size() == (*second).Size())
- return (*first).left <= (*second).left;
- return (*first).Size() > (*second).Size();
- }
- };
- using MemorySegmentHeap =
- Heap<MemorySegmentIterator, MemorySegmentSizeCompare>;
- struct MemorySegmentsHeapObserver {
- void operator() (MemorySegmentIterator segment, size_t new_index) const {
- (*segment).heap_index = new_index;
- }
- };
- class MemoryManager {
- public:
- using Iterator = MemorySegmentIterator;
- using ConstIterator = MemorySegmentConstIterator;
- explicit MemoryManager(size_t memory_size) {
- memory_segments_.push_back(MemorySegment(0, memory_size - 1));
- free_memory_segments_.push(memory_segments_.begin());
- }
- Iterator Allocate(size_t size) {
- if (free_memory_segments_.size() == 0)
- return end();
- MemorySegmentIterator it = free_memory_segments_.top();
- if ((*it).Size() >= size) {
- MemorySegment allocated = { (*it).left, (*it).left + static_cast<int>(size) - 1 };
- allocated.heap_index = MemorySegmentHeap::k_null_index;
- MemorySegmentIterator it_allocated = memory_segments_.insert(it, allocated);
- free_memory_segments_.pop();
- if ((*it).Size() != size) {
- (*it).left += size;
- free_memory_segments_.push(it);
- }
- else {
- memory_segments_.erase(it);
- }
- return it_allocated;
- }
- else {
- return end();
- }
- }
- void Free(Iterator position) {
- if (position == end())
- return;
- if (position != std::prev(memory_segments_.end()))
- AppendIfFree(position, std::next(position));
- if (position != memory_segments_.begin())
- AppendIfFree(position, std::prev(position));
- free_memory_segments_.push(position);
- }
- Iterator end() {
- return memory_segments_.end();
- }
- private:
- MemorySegmentHeap free_memory_segments_ = MemorySegmentHeap(MemorySegmentSizeCompare(),
- MemorySegmentsHeapObserver());
- std::list<MemorySegment> memory_segments_;
- void AppendIfFree(Iterator remaining, Iterator appending) {
- if ((*appending).heap_index != MemorySegmentHeap::k_null_index) {
- free_memory_segments_.erase((*appending).heap_index);
- (*remaining) = (*remaining).Unite((*appending));
- memory_segments_.erase(appending);
- }
- }
- };
- size_t ReadMemorySize(std::istream& stream = std::cin) {
- size_t memory_size;
- stream >> memory_size;
- return memory_size;
- }
- struct AllocationQuery {
- size_t allocation_size;
- };
- struct FreeQuery {
- int allocation_query_index;
- };
- class MemoryManagerQuery {
- public:
- explicit MemoryManagerQuery(AllocationQuery allocation_query)
- : query_(new ConcreteQuery<AllocationQuery>(allocation_query)) {
- }
- explicit MemoryManagerQuery(FreeQuery free_query)
- : query_(new ConcreteQuery<FreeQuery>(free_query)) {
- }
- const AllocationQuery* AsAllocationQuery() const {
- auto ptr = dynamic_cast<ConcreteQuery<AllocationQuery>*>(query_.get()); //NOLINT
- if (ptr)
- return &ptr->body;
- else
- return nullptr;
- }
- const FreeQuery* AsFreeQuery() const {
- auto ptr = dynamic_cast<ConcreteQuery<FreeQuery>*>(query_.get()); //NOLINT
- if (ptr)
- return &(ptr)->body;
- else
- return nullptr;
- }
- private:
- class AbstractQuery {
- public:
- virtual ~AbstractQuery() {
- }
- protected:
- AbstractQuery() {
- }
- };
- template <typename T>
- struct ConcreteQuery : public AbstractQuery {
- T body;
- explicit ConcreteQuery(T _body)
- : body(std::move(_body)) {
- }
- };
- std::unique_ptr<AbstractQuery> query_;
- };
- std::vector<MemoryManagerQuery> ReadMemoryManagerQueries(std::istream& stream = std::cin) {
- int queries_count;
- stream >> queries_count;
- int number;
- std::vector<MemoryManagerQuery> queries_vector;
- for (int i = 0; i < queries_count; ++i) {
- std::cin >> number;
- if (number > 0)
- queries_vector.emplace_back(AllocationQuery({ static_cast<size_t>(number) }));
- else
- queries_vector.emplace_back(FreeQuery({ -number - 1 }));
- }
- return queries_vector;
- }
- struct MemoryManagerAllocationResponse {
- bool success;
- size_t position;
- MemoryManagerAllocationResponse(bool success, size_t position) {
- this->success = success;
- this->position = position;
- };
- };
- MemoryManagerAllocationResponse MakeSuccessfulAllocation(size_t position) {
- return MemoryManagerAllocationResponse(true, position);
- }
- MemoryManagerAllocationResponse MakeFailedAllocation() {
- return MemoryManagerAllocationResponse(false, -1);
- }
- std::vector<MemoryManagerAllocationResponse> RunMemoryManager(
- size_t memory_size,
- const std::vector<MemoryManagerQuery>& queries) {
- MemoryManager memory_manager(memory_size);
- std::vector<MemoryManagerAllocationResponse> responses;
- std::vector<MemorySegmentIterator> iterators;
- for (int it = 0; it < queries.size(); ++it) {
- auto allocation_query = queries[it].AsAllocationQuery();
- if (!allocation_query) {
- auto free_query = queries[it].AsFreeQuery();
- memory_manager.Free(iterators[free_query->allocation_query_index]);
- iterators.push_back(memory_manager.end());
- }
- else {
- auto iterator = memory_manager.Allocate(allocation_query->allocation_size);
- iterators.push_back(iterator);
- if (iterator == memory_manager.end())
- responses.emplace_back(MakeFailedAllocation());
- else
- responses.push_back(MakeSuccessfulAllocation((*iterator).left));
- }
- }
- return responses;
- }
- void OutputMemoryManagerResponses(
- const std::vector<MemoryManagerAllocationResponse>& responses,
- std::ostream& ostream = std::cout) {
- for (auto it : responses) {
- if (it.success == true)
- ostream << it.position + 1 << std::endl;
- else
- ostream << "-1" << std::endl;
- }
- }
- int main() {
- std::istream& input_stream = std::cin;
- std::ostream& output_stream = std::cout;
- const size_t memory_size = ReadMemorySize(input_stream);
- const std::vector<MemoryManagerQuery> queries =
- ReadMemoryManagerQueries(input_stream);
- const std::vector<MemoryManagerAllocationResponse> responses =
- RunMemoryManager(memory_size, queries);
- OutputMemoryManagerResponses(responses, output_stream);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement