Advertisement
Guest User

Untitled

a guest
Jul 17th, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.78 KB | None | 0 0
  1. #include <cstdio>
  2. #include <cinttypes>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <limits>
  6. #include <array>
  7. #include <algorithm>
  8.  
  9. typedef int64_t num_items;
  10.  
  11. namespace bst {
  12. template <class item_key, class item_value> struct bst;
  13.  
  14. template <class item_key, class item_value> struct node {
  15. item_key key;
  16. item_value value;
  17. item_key min;
  18. item_key max;
  19. num_items priority;
  20. num_items size;
  21. bst<item_key, item_value> left;
  22. bst<item_key, item_value> right;
  23. };
  24.  
  25. template <class item_key, class item_value> bst<item_key, item_value> newBstNode(item_key key, item_value value);
  26.  
  27. template <class item_key, class item_value> struct bst {
  28. node<item_key, item_value> *root;
  29. bst() { root = nullptr; }
  30. bst(node<item_key, item_value> *ptr) { root = ptr; }
  31.  
  32. template <class item_key_container, class item_value_container> bst(num_items numItems, item_key_container keyArr, item_value_container valueArr) {
  33. //Return an empty bst if there are no items:
  34. if (numItems == 0) {
  35. root = nullptr;
  36. return;
  37. }
  38.  
  39. //Find where the median is located:
  40. num_items medianPos = numItems/2;
  41. //Create a new node out of the median:
  42. root = newBstNode(keyArr[medianPos], valueArr[medianPos]).root;
  43. //Build the left and right sides accordingly:
  44. root->left = bst<item_key, item_value>(medianPos, keyArr, valueArr);
  45. root->right = bst<item_key, item_value>(numItems-medianPos-1, keyArr+medianPos+1, valueArr+medianPos+1);
  46. //Given the new child nodes, update the bst's properties:
  47. updateProperties();
  48. }
  49.  
  50. num_items getSize() { return (root == nullptr) ? 0 : root->size; }
  51. item_key getMin() { return (root == nullptr) ? std::numeric_limits<item_key>::max() : root->min; }
  52. item_key getMax() { return (root == nullptr) ? std::numeric_limits<item_key>::min() : root->max; }
  53. #ifdef USE_SUM
  54. item_value getSum() { return (root == nullptr) ? 0 : root->sum; }
  55. #endif
  56. void updateProperties() {
  57. if (root != nullptr) {
  58. root->size = 1+root->left.getSize()+root->right.getSize();
  59. root->min = std::min(root->key, std::min(root->left.getMin(), root->right.getMin()));
  60. root->max = std::max(root->key, std::max(root->left.getMax(), root->right.getMax()));
  61. #ifdef USE_SUM
  62. root->sum = root->value+root->left.getSum()+root->right.getSum();
  63. #endif
  64. }
  65. }
  66.  
  67. num_items countItemsInKeyRange(item_key start, item_key end) {
  68. if (root == nullptr) return 0;
  69. //printf("%ld %ld %ld | %ld %ld\n", root->min, root->max, root->size, start, end);
  70. if (start > root->max) return 0;
  71. if (end < root->min) return 0;
  72. if ((start <= root->min) && (end >= root->max)) return root->size;
  73.  
  74. bool rootInInterval = (start <= root->key) && (end >= root->key);
  75. return rootInInterval+root->left.countItemsInKeyRange(start, end)+root->right.countItemsInKeyRange(start, end);
  76. }
  77. };
  78.  
  79. #ifdef USE_STATIC
  80. const num_items MAX_SPACE = 4000000;
  81. template <class item_key, class item_value> node<item_key, item_value> space[MAX_SPACE];
  82. template <class item_key, class item_value> num_items numSpaceUsed = 0;
  83. template <class item_key, class item_value> bst<item_key, item_value> newBstNode(item_key key, item_value value) {
  84. if (numSpaceUsed<item_key, item_value> >= MAX_SPACE) puts("Ran out of bst node space"), exit(1);
  85.  
  86. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].priority = rand();
  87. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].key = key;
  88. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].value = value;
  89. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].left = bst<item_key, item_value>();
  90. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].right = bst<item_key, item_value>();
  91.  
  92. bst<item_key, item_value> newNode(space<item_key, item_value>+numSpaceUsed<item_key, item_value>);
  93. newNode.updateProperties();
  94.  
  95. numSpaceUsed<item_key, item_value>++;
  96. return newNode;
  97. }
  98. #else
  99. template <class item_key, class item_value> bst<item_key, item_value> newBstNode(item_key key, item_value value) {
  100. bst<item_key, item_value> newNode(new node<item_key, item_value>());
  101. newNode.root->priority = rand();
  102. newNode.root->key = key;
  103. newNode.root->value = value;
  104. newNode.root->left = bst<item_key, item_value>();
  105. newNode.root->right = bst<item_key, item_value>();
  106. newNode.updateProperties();
  107. return newNode;
  108. }
  109. #endif
  110.  
  111. //Used to initialize internal bst with empty items:
  112. template <class item_type> struct default_item {
  113. item_type operator*() { return item_type(); }
  114. default_item &operator+(int a) { return *this; }
  115. item_type operator[](int a) { return item_type(); }
  116. };
  117. }
  118.  
  119. namespace range_tree {
  120. //Used with std::sort to sort a bunch of dim-dimensional points by a single coordinate.
  121. template<class item_type, size_t dimension, size_t coord> struct compare_by_coord {
  122. static bool lessThan(const std::array<item_type, dimension> &point1, const std::array<item_type, dimension> &point2) {
  123. for (size_t i = 0; i < dimension; i++) {
  124. size_t indexToBeExamined = (coord+i) % dimension;
  125. if (point1[indexToBeExamined] != point2[indexToBeExamined]) return point1[indexToBeExamined] < point2[indexToBeExamined];
  126. }
  127. return false;
  128. }
  129.  
  130. static bool greaterThan(const std::array<item_type, dimension> &point1, const std::array<item_type, dimension> &point2) {
  131. for (size_t i = 0; i < dimension; i++) {
  132. size_t indexToBeExamined = (coord+i) % dimension;
  133. if (point1[indexToBeExamined] != point2[indexToBeExamined]) return point1[indexToBeExamined] > point2[indexToBeExamined];
  134. }
  135. return false;
  136. }
  137.  
  138. bool operator()(const std::array<item_type, dimension> &point1, const std::array<item_type, dimension> &point2) { return lessThan(point1, point2); }
  139. };
  140.  
  141. //Used to pretend that an array of points is actually an array of coordinates.
  142. //Helpful for building bsts.
  143. template<class item_type, size_t dimension, size_t coord> struct mock_coordinate_array {
  144. std::array<item_type, dimension> *ptr;
  145. mock_coordinate_array(std::array<item_type, dimension> *p) : ptr(p) {}
  146. item_type operator*() { return (*ptr)[coord]; }
  147. mock_coordinate_array operator+(int offset) { return ptr+offset; }
  148. item_type operator[](int offset) { return ptr[offset][coord]; }
  149. };
  150.  
  151. //Used to pretend that an array of points is actually an array of points paired with an empty bst.
  152. //Helpful for building bsts.
  153. template<class point, class bst> struct mock_pair_array {
  154. point *ptr;
  155. mock_pair_array(point *p) : ptr(p) {}
  156. std::pair<point, bst> operator*() { return std::pair<point, bst>(*ptr, bst()); }
  157. mock_pair_array operator+(int offset) { return ptr+offset; }
  158. std::pair<point, bst> operator[](int offset) { return std::pair<point, bst>(ptr[offset], bst()); }
  159. };
  160.  
  161. //subtree<item_type, dim, lev> is a lev-dimensional range tree on a set of dim-dimensional vectors.
  162. //All range trees start as subtree<item_type, dim, dim>, which contains a bunch of subtree<item_type, dim, dim-1>, each of which contains a bunch of subtree<item_type, dim, dim-2>, etc. until we get down to subtree<item_type, dim, 2>
  163. template<class item_type, size_t dimension, size_t level> struct subtree {
  164. bst::bst<item_type, subtree<item_type, dimension, level-1>> internalTree;
  165. };
  166.  
  167. //Alias so people can just use tree<item_type, dim> instead of subtree<item_type, dim, dim>
  168. template <class item_type, size_t dimension> using tree = subtree<item_type, dimension, dimension>;
  169.  
  170. template<class item_type, size_t dimension> struct subtree<item_type, dimension, 2> {
  171. typedef std::array<item_type, dimension> point;
  172. typedef bst::bst<item_type, point> lesser_tree;
  173. typedef std::pair<point, lesser_tree> item_value;
  174. typedef bst::bst<item_type, item_value> internal_tree_type;
  175. internal_tree_type internalTree;
  176.  
  177. static constexpr int MAX_SPACE = 2000000;
  178. static point pointStorageSpace[MAX_SPACE];
  179.  
  180. subtree(num_items numItems, point *points) {
  181. //Sort by the (dimension-2) coordinate:
  182. std::sort(points, points+numItems, compare_by_coord<item_type, dimension, dimension-2>());
  183. //Build the bst by using these unique coordinates as the keys:
  184. internalTree = internal_tree_type(numItems, mock_coordinate_array<item_type, dimension, dimension-2>(points), mock_pair_array<point, lesser_tree>(points));
  185.  
  186. //Sort by the (dimension-1) coordinate:
  187. std::sort(points, points+numItems, compare_by_coord<item_type, dimension, dimension-1>());
  188. //Build the 1D range trees:
  189. buildBstAtNode(internalTree, numItems, points);
  190. }
  191.  
  192. void buildBstAtNode(internal_tree_type node, num_items numItems, point *points) {
  193. if (node.root == nullptr) return;
  194.  
  195. //Build the 1D range tree at this node:
  196. node.root->value.second = lesser_tree(numItems, mock_coordinate_array<item_type, dimension, dimension-1>(points), points);
  197. //Find the number of points that should go in the left and right subtrees, respectively, based off their (dimension-2) coordinate:
  198. //Make sure to preserve the relative order of the elements so we can easily build the 1D range trees in the children nodes.
  199. num_items numLessThanRoot = 0, numGreaterThanRoot = 0;
  200. for (size_t i = 0; i < numItems; i++) {
  201. if (compare_by_coord<item_type, dimension, dimension-2>::lessThan(points[i], node.root->value.first)) pointStorageSpace[numLessThanRoot++] = points[i];
  202. }
  203. for (size_t i = 0; i < numItems; i++) {
  204. if (compare_by_coord<item_type, dimension, dimension-2>::greaterThan(points[i], node.root->value.first)) pointStorageSpace[numLessThanRoot+(numGreaterThanRoot++)] = points[i];
  205. }
  206. //Copy the points over from storage space into the original array:
  207. memcpy(points, pointStorageSpace, (numLessThanRoot+numGreaterThanRoot)*sizeof(point));
  208. //Build the bsts at the children:
  209. buildBstAtNode(node.root->left, numLessThanRoot, points);
  210. buildBstAtNode(node.root->right, numGreaterThanRoot, points+numLessThanRoot);
  211. }
  212.  
  213. num_items countPointsInRange(point minPoint, point maxPoint) {
  214. countPointsInRangeAtNode(internalTree, minPoint, maxPoint);
  215. }
  216.  
  217. num_items countPointsInRangeAtNode(internal_tree_type node, point minPoint, point maxPoint) {
  218. if (node.root == nullptr) return 0;
  219.  
  220. //Get the start and end coordinates for both the (dimension-2) and (dimension-1) coordinates:
  221. item_type startCoord = minPoint[dimension-2], startCoord2 = minPoint[dimension-1];
  222. item_type endCoord = maxPoint[dimension-2], endCoord2 = maxPoint[dimension-1];
  223. //If the query interval is out of range of this node, return 0:
  224. if (startCoord > node.getMax()) return 0;
  225. if (endCoord < node.getMin()) return 0;
  226. //If the node's interval is entirely within the query interval, delegate the query to the 1D range tree:
  227. if ((startCoord <= node.getMin()) && (endCoord >= node.getMax())) return node.root->value.second.countItemsInKeyRange(startCoord2, endCoord2);
  228.  
  229. //Calculate whether or not the root point is within the query interval.
  230. bool rootInInterval = true;
  231. for (size_t i = 0; i < dimension; i++) if ((minPoint[i] > node.root->value.first[i]) || (maxPoint[i] < node.root->value.first[i])) {
  232. rootInInterval = false;
  233. break;
  234. }
  235. //Finally, keep recursing the query to both of the children:
  236. return rootInInterval+countPointsInRangeAtNode(node.root->left, minPoint, maxPoint)+countPointsInRangeAtNode(node.root->right, minPoint, maxPoint);
  237. }
  238. };
  239.  
  240. template<class item_type, size_t dimension> std::array<item_type, dimension> subtree<item_type, dimension, 2>::pointStorageSpace[subtree<item_type, dimension, 2>::MAX_SPACE];
  241. }
  242.  
  243. typedef int32_t num;
  244.  
  245. template<class item_value> void print(bst::bst<num, item_value> tr) {
  246. if (tr.root == nullptr) return;
  247. print(tr.root->left);
  248. printf("%d %d %d %d %d\n", tr.root->key, tr.root->min, tr.root->max, tr.root->value[0], tr.root->value[1]);
  249. print(tr.root->right);
  250. }
  251.  
  252. template<class item_value> void printSpecial(bst::bst<num, item_value> tr) {
  253. if (tr.root == nullptr) return;
  254. printSpecial(tr.root->left);
  255. printf("%d %d %d\n", tr.root->key, tr.root->min, tr.root->max);
  256. puts("---------------------------");
  257. print(tr.root->value.second);
  258. puts("---------------------------");
  259. printSpecial(tr.root->right);
  260. }
  261.  
  262. //#define BULK_TEST
  263.  
  264. #ifdef BULK_TEST
  265. const num_items NUM_ITEMS = 1000000;
  266. std::array<num, 2> points[NUM_ITEMS];
  267. #else
  268. const num_items NUM_ITEMS = 11;
  269. std::array<num, 2> points[NUM_ITEMS] = {{26, 1}, {98, 11}, {90, 8}, {68, 98}, {84, 67}, {13, 7}, {13, 9}, {43, 8}, {32, 77}, {6, 77}, {33, 47}};
  270. #endif
  271.  
  272. int main() {
  273. #ifdef BULK_TEST
  274. for (num_items i = 0; i < NUM_ITEMS; i++) {
  275. points[i][0] = rand();
  276. points[i][1] = rand();
  277. }
  278. #endif
  279. range_tree::tree<num, 2> test(NUM_ITEMS, points);
  280. //print(test.internalTree.root->value.second);
  281. printf("%ld\n", test.internalTree.root->value.second.countItemsInKeyRange(10, 70));
  282. printf("%ld\n", test.countPointsInRange(std::array<num, 2>{10, 0}, std::array<num, 2>{70, 70}));
  283. //printSpecial(test.internalTree); // */
  284.  
  285. /* num_items NUM_ITEMS = 10;
  286. num arr[NUM_ITEMS] = {1, 2, 3, 4, 6, 9, 10, 1203, 2000, 3000};
  287. num arr2[NUM_ITEMS] = {1, 23, 31, -4, 5, 2, 56, 23, 1, 3};
  288. bst::bst<num, num> test(NUM_ITEMS, arr, arr2);
  289. printf("%d\n", test.getSum());
  290. printf("%d\n", test.getKeyRangeSum(1, 10));
  291. for (int i = 0; i < test.getSize(); i++) {
  292. printf("%d\n", test.getNodeAtPos(i).root->value);
  293. } // */
  294. exit(0);
  295. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement