#ifndef INTERVAL_MAP_H #define INTERVAL_MAP_H typedef std::pair interval_t; template class PGF_INTERNAL_DECL interval_map { const static size_t DELTA = 3; const static size_t RATIO = 2; struct Node { size_t sz; size_t start, end, max; Node *left; Node *right; V value; Node(size_t start, size_t end) { this->sz = 1; this->start = start; this->end = end; this->max = end; this->left = NULL; this->right = NULL; memset(&value, 0, sizeof(value)); } }; Node *root; static Node *insert(Node *node, size_t start, size_t end, Node **target) { if (node == NULL) { node = new Node(start, end); *target = node; return node; } int cmp; if (start < node->start) cmp = -1; else if (start > node->start) cmp = 1; else if (end < node->end) cmp = -1; else if (end > node->end) cmp = 1; else cmp = 0; if (cmp < 0) { Node *left = insert(node->left, start, end, target); node = upd_node(node,left,node->right); return balanceL(node); } else if (cmp > 0) { Node *right = insert(node->right, start, end, target); node = upd_node(node,node->left,right); return balanceR(node); } else { *target = node; return node; } } static size_t size(Node *node) { if (node == 0) return 0; return node->sz; } static Node *upd_node(Node *node, Node *left, Node *right) { node->sz = 1+size(left)+size(right); node->max = std::max((left == NULL) ? node->end : left->max, (right == NULL) ? node->end : right->max); node->left = left; node->right = right; return node; } static Node *balanceL(Node *node) { if (node->right == NULL) { if (node->left == NULL) { return node; } else { if (node->left->left == NULL) { if (node->left->right == NULL) { return node; } else { Node *left_right = node->left->right; Node *left = upd_node(node->left,NULL,NULL); Node *right = upd_node(node,NULL,NULL); return upd_node(left_right, left, right); } } else { if (node->left->right == 0) { Node *left = node->left; Node *right = upd_node(node,NULL,NULL); return upd_node(left, left->left, right); } else { if (node->left->right->sz < RATIO * node->left->left->sz) { Node *left = node->left; Node *right = upd_node(node, left->right, NULL); return upd_node(left, left->left, right); } else { Node *left_right = node->left->right; Node *left = upd_node(node->left, node->left->left, left_right->left); Node *right = upd_node(node, left_right->right, NULL); return upd_node(left_right, left, right); } } } } } else { if (node->left == NULL) { return node; } else { if (node->left->sz > DELTA*node->right->sz) { if (node->left->right->sz < RATIO*node->left->left->sz) { Node *left = node->left; Node *right = upd_node(node, left->right, node->right); return upd_node(left, left->left, right); } else { Node *left_right = node->left->right; Node *left = upd_node(node->left, node->left->left, left_right->left); Node *right = upd_node(node, left_right->right, node->right); return upd_node(left_right, left, right); } } else { return node; } } } } static Node *balanceR(Node *node) { if (node->left == NULL) { if (node->right == NULL) { return node; } else { if (node->right->left == NULL) { if (node->right->right == NULL) { return node; } else { Node *right = node->right; Node *left = upd_node(node, NULL, NULL); return upd_node(right, left, right->right); } } else { if (node->right->right == NULL) { Node *right_left = node->right->left; Node *right = upd_node(node->right,NULL,NULL); Node *left = upd_node(node,NULL,NULL); return upd_node(right_left, left, right); } else { if (node->right->left->sz < RATIO * node->right->right->sz) { Node *right = node->right; Node *left = upd_node(node, NULL, right->left); return upd_node(right, left, right->right); } else { Node *right_left = node->right->left; Node *right = upd_node(node->right, right_left->right, node->right->right); Node *left = upd_node(node, NULL, right_left->left); return upd_node(right_left, left, right); } } } } } else { if (node->right == NULL) { return node; } else { if (node->right->sz > DELTA*node->left->sz) { if (node->right->left->sz < RATIO*node->right->right->sz) { Node *right = node->right; Node *left = upd_node(node, node->left, right->left); return upd_node(right, left, right->right); } else { Node *right_left = node->right->left; Node *right = upd_node(node->right, right_left->right, node->right->right); Node *left = upd_node(node, node->left, right_left->left); return upd_node(right_left, left, right); } } else { return node; } } } } public: interval_map() { root = NULL; } V &operator[](interval_t interval) { Node *node; this->root = insert(this->root, interval.first, interval.second, &node); return node->value; } V *lookup(interval_t interval) { return lookup(this->root, interval.first, interval.second); } size_t size() { return size(root); } class iterator { struct Parent { Node *node; Parent *next; }; Parent *spine; public: iterator() { spine = NULL; } iterator(Node *node) { spine = NULL; while (node != NULL) { Parent *parent = new Parent; parent->node = node; parent->next = spine; spine = parent; node = node->left; } } bool operator ==(const iterator other) const { return this->spine == other.spine; } bool operator !=(const iterator other) const { return this->spine != other.spine; } std::pair operator *() const { return std::pair (interval_t(spine->node->start,spine->node->end) ,spine->node->value ); } void operator ++() { Parent *parent = spine->next; Node *node = spine->node->right; delete spine; spine = parent; while (node != NULL) { parent = new Parent; parent->node = node; parent->next = spine; spine = parent; node = node->left; } } ~iterator() { while (spine != NULL) { Parent *parent = spine->next; delete spine; spine = parent; } } }; iterator begin() const { return iterator(root); } iterator end() const { return iterator(); } class Overlaps { Node *root; interval_t i; public: class iterator { struct Parent { Node *node; Parent *next; }; Parent *spine; size_t start, end; public: iterator() { spine = NULL; } iterator(Node *node, size_t start, size_t end) { this->start = start; this->end = end; spine = NULL; for (;;) { Parent *parent; while (node != NULL && start <= node->max) { parent = new Parent; parent->node = node; parent->next = spine; spine = parent; node = node->left; } if (spine == NULL || (start <= spine->node->end && end >= spine->node->start)) return; parent = spine->next; node = spine->node->right; delete spine; spine = parent; } } bool operator ==(const iterator other) const { return this->spine == other.spine; } bool operator !=(const iterator other) const { return this->spine != other.spine; } std::pair operator *() const { return std::pair (interval_t(spine->node->start,spine->node->end) ,spine->node->value ); } void operator ++() { for (;;) { Parent *parent = spine->next; Node *node = spine->node->right; delete spine; spine = parent; while (node != NULL && start <= node->max) { parent = new Parent; parent->node = node; parent->next = spine; spine = parent; node = node->left; } if (spine == NULL || (start <= spine->node->end && end >= spine->node->start)) return; } } ~iterator() { while (spine != NULL) { Parent *parent = spine->next; delete spine; spine = parent; } } }; Overlaps(Node *root, interval_t i) { this->root = root; this->i = i; } iterator begin() const { return iterator(root,i.first,i.second); } iterator end() const { return iterator(); } }; Overlaps overlaps(interval_t interval) { return Overlaps(this->root, interval); } }; #endif