#ifndef CU_H #define CU_H #include #include #include inline long long steady_milli() { return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } inline long long system_milli() { return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); } inline long long steady_micro() { return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } inline long long system_micro() { return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); } template struct SharedData { T data; uint64_t cnt{1}; }; template class SharedPtr { public: SharedPtr(SharedData *ptr = 0) : ptr{ptr} {} SharedPtr(const SharedPtr &other) : ptr{other.ptr} { if(ptr) ptr->cnt++; } ~SharedPtr() { if(ptr==0) return; if(ptr->cnt > 1) ptr->cnt--; else delete ptr; } bool isNull() {return ptr==0;} SharedPtr &operator=(const SharedPtr &other) { this->~SharedPtr(); new (this) SharedPtr(other); return *this; } T &operator*() { if(ptr==0) ptr = new SharedData; return ptr->data; } T *operator->() { if(ptr==0) ptr = new SharedData; return &ptr->data; } const T &operator*() const { return ptr->data; } const T *operator->() const { return &ptr->data; } SharedData *ptr{0}; }; template class Vector : public SharedPtr> { public: using SharedPtr>::SharedPtr; using iterator = std::_Vector_iterator>>; using const_iterator = std::_Vector_const_iterator>>; Vector(std::initializer_list _Ilist) { this->ptr = new SharedData>{_Ilist, 1}; } uint64_t size() const noexcept { return this->ptr ? this->ptr->data.size() : 0; } Vector &append(const V &val) { (**this).push_back(val); return *this; } V &operator[](const uint64_t pos) noexcept { return (**this)[pos]; } const V &operator[](const uint64_t pos) const noexcept { return this->ptr ? this->ptr->data[pos] : V(); } const const_iterator begin() const noexcept { return this->ptr ? this->ptr->data.begin() : const_iterator(); } const const_iterator end() const noexcept { return this->ptr ? this->ptr->data.end() : const_iterator(); } }; struct NodeBase { NodeBase *next{this}; NodeBase *prev{this}; }; template struct _Node : NodeBase { V value; ~_Node() { if(next) delete (_Node*) next; } }; template class LinkedMapIterator { public: LinkedMapIterator(_Node *node) : node(node) {} bool operator==(const LinkedMapIterator& that) const { return node == that.node; } bool operator!=(const LinkedMapIterator& that) const { return node != that.node; } LinkedMapIterator& operator++() { node = (_Node*) node->next; return *this; } LinkedMapIterator& operator--() { node = (_Node*) node->prev; return *this; } V &operator*() const { return node->value; } V *operator->() const { return &node->value; } _Node *node{0}; }; template struct LinkedMapPri : NodeBase { std::unordered_map>*> map; uint64_t cnt{1}; ~LinkedMapPri() { if(prev) prev->next = 0; if(next) delete (_Node>*) next; } }; template class LinkedMap { public: using Node = _Node>; using iterator = LinkedMapIterator>; using const_iterator = LinkedMapIterator>; LinkedMap() {} LinkedMap(std::initializer_list> pairs) : _pri{new LinkedMapPri} { for(auto pair : pairs) insert(pair.first, pair.second); } LinkedMap(std::unordered_map &&map) : _pri{new LinkedMapPri{0, 0, map}} { _pri->next = _pri->prev = _pri; } LinkedMap(const LinkedMap &other) : _pri{other._pri} { if(_pri) _pri->cnt++; } ~LinkedMap() { if(_pri==0) return; if(_pri->cnt > 1) _pri->cnt--; else delete _pri; } LinkedMap &operator=(const LinkedMap &other) { this->~LinkedMap(); new (this) LinkedMap(other); return *this; } const V operator[](const K &k) const { if(_pri==0) return V(); auto it = _pri->map.find(k); if(it==_pri->map.end()) return V(); return it->second->value.second; } LinkedMap &insert(const K &k, const V &v) { if(_pri==0) _pri = new LinkedMapPri; auto pair = _pri->map.emplace(k, nullptr); if(pair.second) { auto node = new Node{_pri, _pri->prev, {k, v}}; _pri->prev->next = node; _pri->prev = node; pair.first->second = node; } else pair.first->second->value.second = v; return *this; } void erase(const K& k) { if(_pri==0) return; auto it = _pri->map.find(k); if(it==_pri->map.end()) return; auto node = it->second; _pri->map.erase(it); node->prev->next = node->next; node->next->prev = node->prev; node->next = 0; node->prev = 0; delete node; } inline bool empty() const { return _pri==0 || _pri->map.empty(); } const_iterator begin() const { return const_iterator((Node*) (_pri ? _pri->next : 0)); } const_iterator end() const { return const_iterator((Node*) _pri); } LinkedMapPri *_pri{0}; }; #endif // CU_H