#ifndef CPP_H
#define CPP_H

#include <chrono>
#include <unordered_map>

inline int64_t steady_milli() {
    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
inline int64_t system_milli() {
    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
inline int64_t steady_micro() {
    return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
inline int64_t system_micro() {
    return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}


template <class T>
struct SharedData {
    size_t cnt{1};
    T data;
};
template <class T>
class SharedPtr {
public:
    SharedPtr(SharedData<T> *ptr = 0) : ptr{ptr} {}
    ~SharedPtr() {
        if(ptr==0) return;
        if(ptr->cnt > 1) ptr->cnt--;
        else delete ptr;
    }

    SharedPtr(const SharedPtr &other) : ptr{other.ptr} {
        if(ptr) ptr->cnt++;
    }
    SharedPtr &operator=(const SharedPtr &other) {
        this->~SharedPtr();
        new (this) SharedPtr(other);
        return *this;
    }
    SharedPtr(SharedPtr &&other) noexcept : ptr(other.ptr) {
        other.ptr = 0;
    }
    SharedPtr &operator=(SharedPtr &&other) noexcept {
        auto aaa = ptr;
        ptr = other.ptr;
        other.ptr = aaa;
        return *this;
    }

    bool isNull() const noexcept {return ptr==0;}
    bool empty() const noexcept {
        return ptr ? ptr->data.empty() : true;
    }
    size_t size() const noexcept {
        return ptr ? ptr->data.size() : 0;
    }

    T &operator*() const {
        if(ptr==0) ptr = new SharedData<T>;
        return ptr->data;
    }
    T *operator->() const {
        if(ptr==0) ptr = new SharedData<T>;
        return &ptr->data;
    }
    bool operator==(const SharedPtr &other) const {
        if(ptr==other.ptr) return true;
        auto siz = size();
        if(siz!=other.size()) return false;
        if(siz==0) return true;
        return ptr->data==other.ptr->data;
    }
    bool operator!=(const SharedPtr &other) const {
        return ! (*this==other);
    }
    mutable SharedData<T> *ptr = 0;
};


template <class V>
class Vector : public SharedPtr<std::vector<V>> {
public:
    using SharedPtr<std::vector<V>>::SharedPtr;

    using iterator       = std::_Vector_iterator<std::_Vector_val<std::_Simple_types<V>>>;
    using const_iterator = std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<V>>>;

    Vector(std::initializer_list<V> _Ilist) {
        this->ptr = new SharedData<std::vector<V>>{1, _Ilist};
    }

    Vector &append(const V &val) {
        (*this)->push_back(val);
        return *this;
    }
    Vector &append(V&& val) {
        (*this)->push_back(_STD move(val));
        return *this;
    }
    Vector &operator<<(const V &val) {
        (*this)->push_back(val);
        return *this;
    }
    Vector &operator<<(V&& val) {
        (*this)->push_back(_STD move(val));
        return *this;
    }

    V &operator[](const uint64_t pos) noexcept {
        return (**this)[pos];
    }
    const V &operator[](const uint64_t pos) const noexcept {
        return (**this)[pos];
    }

    iterator begin() const noexcept {
        return this->ptr ? this->ptr->data.begin() : iterator();
    }
    iterator end() const noexcept {
        return this->ptr ? this->ptr->data.end() : iterator();
    }
};


struct NodeBase {
    NodeBase *next{this};
    NodeBase *prev{this};
};
template <class P>
struct _Node : NodeBase {
    P value;
    ~_Node() {
        if(next) delete (_Node<P>*) next;
    }
};

template <class P>
class LinkedMapIterator {
public:
    LinkedMapIterator(_Node<P> *node) : node(node) {}
    bool operator==(const LinkedMapIterator& other) const noexcept {
        return node == other.node;
    }
    bool operator!=(const LinkedMapIterator& other) const noexcept {
        return node != other.node;
    }
    LinkedMapIterator& operator++() {
        node = (_Node<P>*) node->next;
        return *this;
    }
    LinkedMapIterator& operator--() {
        node = (_Node<P>*) node->prev;
        return *this;
    }
    const LinkedMapIterator operator++(int) {
        auto rtn = *this;
        node = (_Node<P>*) node->next;
        return rtn;
    }
    const LinkedMapIterator operator--(int) {
        auto rtn = *this;
        node = (_Node<P>*) node->prev;
        return rtn;
    }
    P &operator*() const noexcept {
        return node->value;
    }
    P *operator->() const noexcept {
        return &node->value;
    }
    _Node<P> *node{0};
};

template <class K, class V>
struct LinkedMapPri : NodeBase {
    size_t cnt = 1;
    std::unordered_map<K, _Node<std::pair<K, V>>*> map;
    ~LinkedMapPri() {
        if(prev) prev->next = 0;
        if(next) delete (_Node<std::pair<K, V>>*) next;
    }
};
template <class K, class V>
class LinkedMap {
public:
    using Node = _Node<std::pair<K, V>>;

    using iterator       = LinkedMapIterator<std::pair<K, V>>;
    using const_iterator = LinkedMapIterator<std::pair<K, V>>;

    LinkedMap() {}
    LinkedMap(std::initializer_list<std::pair<K, V>> pairs) : _pri{new LinkedMapPri<K, V>} {
        for(auto &pair : pairs) insert(pair.first, pair.second);
    }
    LinkedMap(std::unordered_map<K, Node*> &&map) : _pri{new LinkedMapPri<K, V>{0, 0, map}} {
        _pri->next = _pri->prev = _pri;
    }
    ~LinkedMap() {
        if(_pri==0) return;
        if(_pri->cnt > 1) _pri->cnt--;
        else delete _pri;
    }

    LinkedMap(const LinkedMap &other) : _pri{other._pri} {
        if(_pri) _pri->cnt++;
    }
    LinkedMap &operator=(const LinkedMap &other) {
        this->~LinkedMap();
        new (this) LinkedMap(other);
        return *this;
    }
    LinkedMap(LinkedMap &&other) noexcept : _pri(other._pri) {
        other._pri = 0;
    }
    LinkedMap &operator=(LinkedMap &&other) noexcept {
        auto aaa = _pri;
        _pri = other._pri;
        other._pri = aaa;
        return *this;
    }

    bool empty() const noexcept {
        return _pri==0 || _pri->map.empty();
    }
    size_t size() const noexcept {
        return _pri ? _pri->map.size() : 0;
    }

    iterator find(const K &k) const {
        if(_pri==0) return iterator((Node*) _pri);
        auto it = _pri->map.find(k);
        if(it==_pri->map.end()) return iterator((Node*) _pri);
        return iterator(it->second);
    }
    const V operator()(const K &k) const {
        return (*this)[k];
    }
    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;
    }
    V &operator[](const K &k) {
        if(_pri==0) _pri = new LinkedMapPri<K, V>;
        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;
        }
        return pair.first->second->value.second;
    }

    LinkedMap &insert(const K &k, const V &v) {
        if(_pri==0) _pri = new LinkedMapPri<K, V>;
        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;
    }
    V remove(const K& k) {
        if(_pri==0) return V();
        auto it = _pri->map.find(k);
        if(it==_pri->map.end()) return V();
        auto node = it->second;
        _pri->map.erase(it);
        node->prev->next = node->next;
        node->next->prev = node->prev;
        node->next = 0;
        node->prev = 0;
        auto v = node->value.second;
        delete node;
        return v;
    }
    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;
    }

    bool operator==(const LinkedMap &other) const {
        if(_pri==other._pri) return true;
        auto siz = size();
        if(siz!=other.size()) return false;
        if(siz==0) return true;
        auto aaa = begin();
        auto bbb = other.begin();
        while(aaa!=end()) {
            if(aaa->first != bbb->first || aaa->second != bbb->second) return false;
            ++aaa;
            ++bbb;
        }
        return true;
    }
    bool operator!=(const LinkedMap &other) const {
        return ! (*this==other);
    }

    iterator begin() const {
        return iterator((Node*) (_pri ? _pri->next : 0));
    }
    iterator end() const {
        return iterator((Node*) _pri);
    }
    LinkedMapPri<K, V> *_pri = 0;
};

#endif // CPP_H