Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <list>
- #include <assert.h>
- #include <fstream>
- struct MemoryBlock {
- size_t start_index;
- size_t size;
- size_t heap_index;
- bool is_free;
- };
- struct HeapElement {
- std::list<MemoryBlock>::iterator iter;
- };
- class Heap {
- public:
- HeapElement PopTop() {
- HeapElement result = storage_[0];
- Swap(0, storage_.size() - 1);
- storage_.pop_back();
- SinkDown(0);
- return result;
- }
- std::list<MemoryBlock>::iterator PeekTop() {
- return storage_[0].iter;
- }
- void Delete(size_t i_) {
- Swap(i_, storage_.size() - 1);
- storage_.pop_back();
- SinkDown(i_);
- }
- size_t Size() {
- return storage_.size();
- }
- void Insert(HeapElement new_element) {
- storage_.push_back(new_element);
- storage_[storage_.size() - 1].iter->heap_index = storage_.size() - 1;
- BubbleUp(storage_.size() - 1);
- }
- void BubbleUp(size_t i_) {
- while (i_ > 0) {
- size_t parent_idx = (i_ - 1) / 2;
- if (CmpLt(parent_idx, i_)) {
- Swap(parent_idx, i_);
- i_ = parent_idx;
- } else {
- break;
- }
- }
- }
- void SinkDown(size_t i_) {
- size_t length = storage_.size();
- while (i_ < length) {
- size_t left_child_idx = 2 * i_ + 1;
- size_t right_child_idx = 2 * i_ + 2;
- size_t min_index = i_;
- if (left_child_idx < length && CmpLt(i_, left_child_idx)) {
- min_index = left_child_idx;
- }
- if (right_child_idx < length && CmpLt(i_, right_child_idx)) {
- min_index = right_child_idx;
- }
- if (i_ != min_index) {
- Swap(i_, min_index);
- i_ = min_index;
- } else {
- break;
- }
- }
- }
- private:
- bool CmpLt(size_t i_, size_t j_) {
- if (storage_[i_].iter->size == storage_[j_].iter->size) {
- return storage_[i_].iter->start_index > storage_[j_].iter->start_index;
- } else {
- return storage_[i_].iter->size < storage_[j_].iter->size;
- }
- }
- void Swap(size_t i_, size_t j_) {
- HeapElement swap_elem = storage_[i_];
- storage_[i_] = storage_[j_];
- storage_[j_] = swap_elem;
- storage_[i_].iter->heap_index = i_;
- storage_[j_].iter->heap_index = j_;
- }
- std::vector<HeapElement> storage_;
- };
- struct AllocationEvent {
- bool success;
- std::list<MemoryBlock>::iterator memory_block_iter;
- };
- class MemoryManager {
- public:
- explicit MemoryManager(size_t memory_size) {
- MemoryBlock new_block;
- new_block.start_index = 1;
- new_block.size = memory_size;
- new_block.is_free = true;
- blocks_list_.push_front(new_block);
- std::list<MemoryBlock>::iterator iter = blocks_list_.begin();
- HeapElement new_elem;
- new_elem.iter = iter;
- free_heap_.Insert(new_elem);
- // Push into memory_heap
- }
- bool Allocate(size_t size_needed) {
- auto max_block = free_heap_.PeekTop();
- if (max_block->size < size_needed) {
- AllocationEvent event;
- event.success = false;
- allocation_history_.push_back(event);
- std::cout << -1 << "\n";
- return false;
- } else {
- auto new_occupied_block = SplitOccupy(max_block, size_needed);
- AllocationEvent event;
- event.success = true;
- event.memory_block_iter = new_occupied_block;
- allocation_history_.push_back(event);
- std::cout << new_occupied_block->start_index << "\n";
- return true;
- }
- }
- void Free(size_t when_occupied) {
- when_occupied--;
- if (allocation_history_[when_occupied].success) {
- allocation_history_[when_occupied].success = false;
- auto occupied_iter = allocation_history_[when_occupied].memory_block_iter;
- if (occupied_iter == blocks_list_.begin()) {
- auto next_block = occupied_iter;
- next_block++;
- if (next_block == blocks_list_.end()) {
- FreeIsolated(occupied_iter);
- } else {
- if (!next_block->is_free) {
- FreeIsolated(occupied_iter);
- } else {
- FreeBefore(occupied_iter, next_block);
- }
- }
- } else {
- auto previous_block = occupied_iter;
- previous_block--;
- auto next_block = occupied_iter;
- next_block++;
- if (next_block == blocks_list_.end()) {
- if (!previous_block->is_free) {
- FreeIsolated(occupied_iter);
- } else {
- FreeAfter(previous_block, occupied_iter);
- }
- } else {
- if (!previous_block->is_free && !next_block->is_free) {
- FreeIsolated(occupied_iter);
- } else if (!previous_block->is_free && next_block->is_free) {
- FreeBefore(occupied_iter, next_block);
- } else if (previous_block->is_free && !next_block->is_free) {
- FreeAfter(previous_block, occupied_iter);
- } else if (previous_block->is_free && next_block->is_free) {
- previous_block->size += occupied_iter->size + next_block->size;
- free_heap_.Delete(next_block->heap_index);
- blocks_list_.erase(next_block);
- blocks_list_.erase(occupied_iter);
- free_heap_.BubbleUp(previous_block->heap_index);
- }
- }
- }
- }
- }
- private:
- void FreeIsolated(std::list<MemoryBlock>::iterator occupied_iter) {
- occupied_iter->is_free = true;
- HeapElement new_elem;
- new_elem.iter = occupied_iter;
- free_heap_.Insert(new_elem);
- }
- void FreeBefore(std::list<MemoryBlock>::iterator occupied_iter,
- std::list<MemoryBlock>::iterator next_block) {
- occupied_iter->is_free = true;
- next_block->size += occupied_iter->size;
- next_block->start_index = occupied_iter->start_index;
- free_heap_.BubbleUp(next_block->heap_index);
- blocks_list_.erase(occupied_iter);
- }
- void FreeAfter(std::list<MemoryBlock>::iterator previous_block,
- std::list<MemoryBlock>::iterator occupied_iter) {
- previous_block->size += occupied_iter->size;
- free_heap_.BubbleUp(previous_block->heap_index);
- blocks_list_.erase(occupied_iter);
- }
- std::list<MemoryBlock>::iterator SplitOccupy(std::list<MemoryBlock>::iterator iter,
- size_t size_needed) {
- assert(iter->size >= size_needed);
- assert(iter->is_free);
- if (iter->size > size_needed) {
- MemoryBlock new_occupied_block;
- new_occupied_block.is_free = false;
- new_occupied_block.start_index = iter->start_index;
- new_occupied_block.size = size_needed;
- iter->size -= size_needed;
- iter->start_index = new_occupied_block.start_index + size_needed;
- free_heap_.SinkDown(iter->heap_index);
- auto new_occupied_iter = blocks_list_.insert(iter, new_occupied_block);
- return new_occupied_iter;
- } else {
- iter->is_free = false;
- free_heap_.Delete(iter->heap_index);
- return iter;
- }
- }
- std::list<MemoryBlock> blocks_list_;
- Heap free_heap_;
- std::vector<AllocationEvent> allocation_history_;
- };
- struct Query {
- bool is_alloc;
- size_t value;
- Query(bool is_alloc_, size_t value_)
- : is_alloc(is_alloc_), value(value_) {}
- };
- void ReadInput(const std::string& filename,
- size_t* memory_size, std::vector<int64_t>* queries) {
- std::ifstream in_stream;
- in_stream.open(filename);
- if (!in_stream.is_open()) {
- std::cerr << "File not found:" << filename;
- exit(1);
- }
- size_t num_queries;
- in_stream >> *memory_size >> num_queries;
- // std::cout << *memory_size << " " << num_queries << std::endl;
- queries->resize(num_queries);
- for (auto& query : *queries) {
- in_stream >> query;
- }
- }
- int main() {
- std::string filename = "input.txt";
- size_t memory_size;
- std::vector<int64_t> queries;
- ReadInput(filename, &memory_size, &queries);
- MemoryManager mgr(memory_size);
- for (const auto& query : queries) {
- // std::cout << query << std::endl;
- if (query > 0) {
- mgr.Allocate(static_cast<size_t>(query));
- } else {
- mgr.Free(static_cast<size_t>(-query));
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement