Advertisement
Guest User

Untitled

a guest
Jul 17th, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.72 KB | None | 0 0
  1. #include <cstdio>
  2. #include <cinttypes>
  3. #include <cstdlib>
  4. #include <limits>
  5. #include <array>
  6. #include <algorithm>
  7.  
  8. typedef int64_t num_items;
  9.  
  10. namespace treap {
  11. template <class item_key, class item_value> struct treap;
  12.  
  13. template <class item_key, class item_value> struct node {
  14. item_key key;
  15. item_value value;
  16. item_key min;
  17. item_key max;
  18. num_items priority;
  19. num_items size;
  20. treap<item_key, item_value> left;
  21. treap<item_key, item_value> right;
  22. };
  23.  
  24. template <class item_key, class item_value> struct treap_pair {
  25. treap<item_key, item_value> left;
  26. treap<item_key, item_value> right;
  27. treap_pair() : left(nullptr), right(nullptr) {};
  28. };
  29.  
  30. template <class item_key, class item_value> treap<item_key, item_value> newTreapNode(item_key key, item_value value);
  31.  
  32. template <class item_key, class item_value> struct treap {
  33. node<item_key, item_value> *root;
  34. treap() { root = nullptr; }
  35. treap(node<item_key, item_value> *ptr) { root = ptr; }
  36.  
  37. template <class item_key_container, class item_value_container> treap(num_items numItems, item_key_container keyArr, item_value_container valueArr) {
  38. //Return an empty treap if there are no items:
  39. if (numItems == 0) {
  40. root = nullptr;
  41. return;
  42. }
  43. //Return a treap with one item if there is an item:
  44. if (numItems == 1) {
  45. root = nullptr;
  46. addElementByKey(*keyArr, *valueArr, false);
  47. return;
  48. }
  49.  
  50. //Find where the median is located:
  51. num_items medianPos = numItems/2;
  52. //Build the left and right sides accordingly:
  53. treap<item_key, item_value> leftSide(medianPos, keyArr, valueArr);
  54. treap<item_key, item_value> rightSide(numItems-medianPos, keyArr+medianPos, valueArr+medianPos);
  55. //Merge the two treaps together:
  56. root = mergeTreaps(leftSide, rightSide).root;
  57. }
  58.  
  59. num_items getSize() { return (root == nullptr) ? 0 : root->size; }
  60. item_key getMin() { return (root == nullptr) ? std::numeric_limits<item_key>::max() : root->min; }
  61. item_key getMax() { return (root == nullptr) ? std::numeric_limits<item_key>::min() : root->max; }
  62. void updateProperties() {
  63. if (root != nullptr) {
  64. root->size = 1+root->left.getSize()+root->right.getSize();
  65. root->min = std::min(root->key, std::min(root->left.getMin(), root->right.getMin()));
  66. root->max = std::max(root->key, std::max(root->left.getMax(), root->right.getMax()));
  67. }
  68. }
  69.  
  70. static treap<item_key, item_value> mergeTreaps(treap<item_key, item_value> left, treap<item_key, item_value> right) {
  71. if (left.root == nullptr) return right;
  72. if (right.root == nullptr) return left;
  73. if (left.root->priority > right.root->priority) {
  74. left.root->right = mergeTreaps(left.root->right, right);
  75. left.updateProperties();
  76. return left;
  77. } else {
  78. right.root->left = mergeTreaps(left, right.root->left);
  79. right.updateProperties();
  80. return right;
  81. }
  82. }
  83.  
  84. //Split treap into a left-side with all elements less than or equal to key and a right-side with the rest of the elements.
  85. //Note that if exclusive is true, then left-side will have all elements less than key and right-side will have all elements greater than or equal to key.
  86. treap_pair<item_key, item_value> splitByKey(item_key key, bool exclusive) {
  87. treap_pair<item_key, item_value> answer;
  88. if (root == nullptr) return answer;
  89.  
  90. //If the key is less than the key of the root, then all items less than or equal to key are on the left-hand side.
  91. if (exclusive ? (key <= root->key) : (key < root->key)) {
  92. answer = root->left.splitByKey(key, exclusive);
  93. //Since answer.left is the tree rooted at key, make answer.right, which has all elements greater than key but less than the key of the root, the new left node of the treap:
  94. root->left = answer.right;
  95. //After making this modification, this becomes the right-side, which has all elements greater than key:
  96. answer.right = *this;
  97. }
  98. //If the key is greater than or equal to the key of the root, then we know that the left-side and the root is composed of all elements less than or equal to key, so we need to search the right-hand side for any other elements which are less than or equal to key.
  99. else {
  100. answer = root->right.splitByKey(key, exclusive);
  101. //Now, we need to combine this treap and its left-side with all of the elements in the right-side which are also less than or equal to key.
  102. //These elements are now in answer.left, so make answer.left the new right-side of treap:
  103. root->right = answer.left;
  104. //After making this modification, this becomes the left-side, which has all elements less than or equal to key:
  105. answer.left = *this;
  106. }
  107. updateProperties();
  108. return answer;
  109. }
  110.  
  111. item_value getKeyRangeSum(item_key startKey, item_key endKey) {
  112. //Split the treap up into a left-side which has all elements up to endKey:
  113. treap_pair<item_key, item_value> parts = splitByKey(endKey, false);
  114. //Split that treap up into a left-side which has all elements up to startKey-1:
  115. treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(startKey, true);
  116. //Get the sum of the elements greater than startKey, less than or equal to endKey:
  117. item_value result = parts2.right.getSum();
  118. //Merge the treaps back together:
  119. root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
  120. return result;
  121. }
  122.  
  123. num_items countPointsInKeyRange(item_key startKey, item_key endKey) {
  124. //Split the treap up into a left-side which has all elements up to endKey:
  125. treap_pair<item_key, item_value> parts = splitByKey(endKey, false);
  126. //Split that treap up into a left-side which has all elements up to startKey-1:
  127. treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(startKey, true);
  128. //Get the number of the elements greater than startKey, less than or equal to endKey:
  129. num_items result = parts2.right.getSize();
  130. //Merge the treaps back together:
  131. root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
  132. return result;
  133. }
  134.  
  135. bool addElementByKey(item_key newKey, item_value newValue, bool exclusive) {
  136. //Split treap up into a left-side with all elements less than newKey:
  137. treap_pair<item_key, item_value> parts = splitByKey(newKey, false);
  138. //Make sure newKey is not already in the tree:
  139. if (exclusive) {
  140. treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(newKey, true);
  141. if (parts2.right.root != nullptr) {
  142. root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
  143. return false;
  144. }
  145. parts.left = mergeTreaps(parts2.left, parts2.right);
  146. }
  147.  
  148. //Create a new node:
  149. treap<item_key, item_value> storeTreap = newTreapNode<item_key, item_value>(newKey, newValue);
  150. //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
  151. root = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right).root;
  152.  
  153. return true;
  154. }
  155.  
  156. bool removeElementByKey(item_key oldKey) {
  157. //Split treap up into a left-side which has all elements up to oldKey:
  158. treap_pair<item_key, item_value> parts = splitByKey(oldKey, false);
  159. //Now, split the left-side up into a left-side which has all elements before oldKey and a right-side which has all elements equal to oldKey:
  160. treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(oldKey, true);
  161. //Record whether there were actually any elements with oldKey:
  162. bool actuallyRemoved = parts2.right.root != nullptr;
  163. //Merge treaps back together without the elements equal to oldKey:
  164. root = mergeTreaps(parts2.left, parts.right).root;
  165.  
  166. return actuallyRemoved;
  167. }
  168.  
  169. //Split treap into a left-side with the first pos elements and a right-side with the rest of the elements.
  170. //The left-side will be rooted with the (pos-1)th item (0-based indexing), if it exists.
  171. treap_pair<item_key, item_value> splitByPos(num_items pos) {
  172. treap_pair<item_key, item_value> answer;
  173. if (this->root == nullptr) return answer;
  174. if (pos > getSize()) {
  175. answer.left = *this;
  176. return answer;
  177. }
  178.  
  179. num_items leftSize = root->left.getSize();
  180. //If the left-side has pos elements or more, then the (pos-1)th element is on the left-side:
  181. if (pos <= leftSize) {
  182. answer = root->left.splitByPos(pos);
  183. //Since answer.left is the tree rooted at (pos-1)th element, make answer.right, the elements between the (pos-1)th element and the root, the new left node of the treap:
  184. root->left = answer.right;
  185. //After making this modification, treap1 becomes the right-side, which has all elements after the (pos-1)th one:
  186. answer.right = *this;
  187. }
  188. //Otherwise, we need to split the right-side up to look for the (pos-1)th element:
  189. else {
  190. //Notice that we subtract pos by the number of elements in the root and left-side:
  191. answer = root->right.splitByPos(pos-leftSize-1);
  192. //Now, in order to get all of the first pos elements, we need to combine treap1 and its left-side with all of the elements in the right-side.
  193. //These elements are now in answer.left, so make answer.left the new right-side of treap:
  194. root->right = answer.left;
  195. //After making this modification, treap1 becomes the left-side, which has all of the first pos elements:
  196. answer.left = *this;
  197. }
  198. updateProperties();
  199. return answer;
  200. }
  201.  
  202. item_value getIntervalSum(num_items startPos, num_items endPos) {
  203. //Split the treap up into a left-side which has all elements up to endPos index:
  204. treap_pair<item_key, item_value> parts = splitByPos(endPos+1);
  205. //Split that treap up into a left-side which has all elements up to startPos-1 index:
  206. treap_pair<item_key, item_value> parts2 = parts.left.splitByPos(startPos);
  207. //Get the sum of the elements with index greater than startPos-1, less than or equal to endPos:
  208. item_value result = parts2.right.getSum();
  209. //Merge the treaps back together:
  210. root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
  211. return result;
  212. }
  213.  
  214. void addElementByPos(num_items newPos, item_key newKey, item_value newValue) {
  215. //Split treap up into a left-side with first pos elements:
  216. treap_pair<item_key, item_value> parts = splitByPos(newPos);
  217. //Create the new node:
  218. treap<item_key, item_value> storeTreap = newTreapNode<item_key, item_value>(newKey, newValue);
  219. //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
  220. root = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right).root;
  221. }
  222.  
  223. bool removeElementByPos(num_items oldPos) {
  224. //If the index is too big or too small, we can't remove it:
  225. if (oldPos+1 > getSize()) return false;
  226. if (oldPos < 0) return false;
  227.  
  228. //Split treap up into a left-side which has the first (oldPos+1) elements:
  229. treap_pair<item_key, item_value> parts = splitByPos(oldPos+1);
  230. //Now, separate out the first oldPos elements from this left-side in order to isolate the (oldPos)th element:
  231. treap_pair<item_key, item_value> parts2 = parts.left.splitByPos(oldPos);
  232. //Merge treaps back together without the isolated element:
  233. root = mergeTreaps(parts2.left, parts.right).root;
  234.  
  235. return true;
  236. }
  237.  
  238. treap getNodeAtPos(num_items pos) {
  239. //If the index is too big or too small, we can't find its value:
  240. if (pos < 0) return nullptr;
  241. if (pos > getSize()) return nullptr;
  242.  
  243. treap<item_key, item_value> curTreap = *this;
  244. //Keep looking for the treap whose root is the (pos)th element:
  245. while (curTreap.root->left.getSize() != pos) {
  246. //If the left subtree has less than pos elements, then the (pos)th element must be in the right subtree.
  247. //Also, adjust pos accordingly.
  248. if (curTreap.root->left.getSize() < pos) {
  249. pos -= curTreap.root->left.getSize()+1;
  250. curTreap = curTreap.root->right;
  251. }
  252. //Otherwise, the (pos)th element must be in the left subtree.
  253. else curTreap = curTreap.root->left;
  254.  
  255. if (curTreap.root == nullptr) puts("Treap size values are corrupted"), exit(1);
  256. }
  257. //Finally, return the treap that we just found:
  258. return curTreap;
  259. }
  260. };
  261.  
  262.  
  263. const num_items MAX_SPACE = 4000000;
  264. template <class item_key, class item_value> node<item_key, item_value> space[MAX_SPACE];
  265. template <class item_key, class item_value> num_items numSpaceUsed;
  266. template <class item_key, class item_value> treap<item_key, item_value> newTreapNode(item_key key, item_value value) {
  267. if (numSpaceUsed<item_key, item_value> >= MAX_SPACE) puts("Ran out of treap node space"), exit(1);
  268.  
  269. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].priority = rand();
  270. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].key = key;
  271. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].value = value;
  272. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].left = treap<item_key, item_value>();
  273. space<item_key, item_value>[numSpaceUsed<item_key, item_value>].right = treap<item_key, item_value>();
  274.  
  275. treap<item_key, item_value> newNode(space<item_key, item_value>+numSpaceUsed<item_key, item_value>);
  276. newNode.updateProperties();
  277.  
  278. numSpaceUsed<item_key, item_value>++;
  279. return newNode;
  280. }
  281.  
  282. //Used to initialize internal treap with empty items:
  283. template <class item_type> struct default_item {
  284. item_type operator*() { return item_type(); }
  285. default_item &operator+(int a) { return *this; }
  286. };
  287. }
  288.  
  289. namespace range_tree {
  290. //Used with std::sort to sort a bunch of dim-dimensional points by a single coordinate.
  291. template<class item_type, ssize_t dimension, ssize_t coord> struct compare_by_coord {
  292. bool operator()(const std::array<item_type, dimension> &point1, const std::array<item_type, dimension> &point2) {
  293. return point1[coord] < point2[coord];
  294. }
  295. };
  296.  
  297. //Used to pretend that an array of points is actually an array of coordinates.
  298. //Helpful for building treaps.
  299. template<class item_type, ssize_t dimension, ssize_t coord> struct mock_coordinate_array {
  300. std::array<item_type, dimension> *ptr;
  301. mock_coordinate_array(std::array<item_type, dimension> *p) : ptr(p) {}
  302. item_type operator*() { return (*ptr)[coord]; }
  303. mock_coordinate_array operator+(int offset) { return ptr+offset; }
  304. };
  305.  
  306. //subtree<item_type, dim, lev> is a lev-dimensional range tree on a set of dim-dimensional vectors.
  307. //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>
  308. template<class item_type, ssize_t dimension, ssize_t level> struct subtree {
  309. treap::treap<item_type, subtree<item_type, dimension, level-1>> internalTree;
  310. };
  311.  
  312. //Alias so people can just use tree<item_type, dim> instead of subtree<item_type, dim, dim>
  313. template <class item_type, ssize_t dimension> using tree = subtree<item_type, dimension, dimension>;
  314.  
  315. template<class item_type, ssize_t dimension> struct subtree<item_type, dimension, 2> {
  316. typedef std::array<item_type, dimension> point;
  317. typedef treap::treap<item_type, point> item_value;
  318. typedef treap::treap<item_type, item_value> internal_tree_type;
  319. internal_tree_type internalTree;
  320.  
  321. static constexpr int MAX_SPACE = 2000000;
  322. static item_type itemStorageSpace[MAX_SPACE];
  323. static std::array<item_type, dimension> pointStorageSpace[MAX_SPACE];
  324.  
  325. subtree(num_items numItems, point *points) {
  326. //Sort by the (dimension-2) coordinate:
  327. std::sort(points, points+numItems, compare_by_coord<item_type, dimension, dimension-2>());
  328. //Find how many unique (dimension-2) coordinates there are among the points:
  329. num_items numUniqueCoords = 0;
  330. for (num_items i = 0; i < numItems; i++) {
  331. if ((i == 0) || (points[i][dimension-2] != points[i-1][dimension-2])) itemStorageSpace[numUniqueCoords++] = points[i][dimension-2];
  332. }
  333. //Build the treap by using these unique coordinates as the keys:
  334. internalTree = internal_tree_type(numUniqueCoords, itemStorageSpace, treap::default_item<item_value>());
  335.  
  336. //Sort by the (dimension-1) coordinate:
  337. std::sort(points, points+numItems, compare_by_coord<item_type, dimension, dimension-1>());
  338. //Build the 1D range trees:
  339. buildTreapAtNode(internalTree, numItems, points);
  340. }
  341.  
  342. void buildTreapAtNode(internal_tree_type node, num_items numItems, point *points) {
  343. if (node.root == nullptr) return;
  344.  
  345. //Build the 1D range tree at this node:
  346. node.root->value = item_value(numItems, mock_coordinate_array<item_type, dimension, dimension-1>(points), points);
  347. //Find the number of points that should go in the left and right subtrees, respectively, based off their (dimension-2) coordinate:
  348. num_items numLessThanRoot = 0, numGreaterThanRoot = 0;
  349. for (num_items i = 0; i < numItems; i++) {
  350. if (points[i][dimension-2] < node.root->key) pointStorageSpace[numLessThanRoot++] = points[i];
  351. if (points[i][dimension-2] < node.root->key) pointStorageSpace[numItems-(++numGreaterThanRoot)] = points[i];
  352. }
  353. //Copy the points over from storage space into the original array:
  354. memcpy(points, pointStorageSpace, numItems*sizeof(point));
  355. //Build the treaps at the children:
  356.  
  357. }
  358. };
  359.  
  360. template<class item_type, ssize_t dimension> item_type subtree<item_type, dimension, 2>::itemStorageSpace[subtree<item_type, dimension, 2>::MAX_SPACE];
  361. }
  362.  
  363. typedef int32_t num;
  364.  
  365. template<class item_value> void print(treap::treap<num, item_value> tr) {
  366. if (tr.root == nullptr) return;
  367. print(tr.root->left);
  368. printf("%d %d %d %d %d\n", tr.root->key, tr.root->min, tr.root->max, tr.root->value[0], tr.root->value[1]);
  369. print(tr.root->right);
  370. }
  371.  
  372. int main() {
  373. num_items NUM_ITEMS = 11;
  374. 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}};
  375. range_tree::tree<num, 2> test(NUM_ITEMS, points);
  376. print(test.internalTree.root->value);
  377.  
  378. /* num_items NUM_ITEMS = 10;
  379. int32_t arr[NUM_ITEMS] = {1, 2, 3, 4, 6, 9, 10, 1203, 2000, 3000};
  380. int32_t arr2[NUM_ITEMS] = {1, 23, 31, -4, 5, 2, 56, 23, 1, 3};
  381. treap::treap<int32_t, int32_t> test(NUM_ITEMS, arr, default_item());
  382. for (int i = 0; i < test.getSize(); i++) {
  383. printf("%d\n", test.getNodeAtPos(i).root->value);
  384. } // */
  385. exit(0);
  386. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement