Guest User

Untitled

a guest
Nov 20th, 2018
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.39 KB | None | 0 0
  1. ;; Package for Range Maximum Query (RMQ) operations using Segment Trees.
  2. ;; Implemented in Racket v5.2.1.
  3. ;; Author: Viswanath Sivakumar <viswanathgs@gmail.com>
  4.  
  5. ;; Abstraction for integer ranges.
  6. (define make-range
  7. (lambda (low high) (cons low high)))
  8. (define low
  9. (lambda (range) (car range)))
  10. (define high
  11. (lambda (range) (cdr range)))
  12. (define integer-inside-range?
  13. ;; Checks if an integer falls within a range.
  14. (lambda (i r) (and (>= i (low r)) (<= i (high r)))))
  15. (define range-inside-range?
  16. ;; Checks if range r1 falls within range r2.
  17. (lambda (r1 r2) (and (>= (low r1) (low r2)) (<= (high r1) (high r2)))))
  18.  
  19. ;; Abstraction for segment trees.
  20. ;; Each node is represented as a list of value, range and left and right sub-trees.
  21. (define make-segment-tree
  22. (lambda (value range left right) (list value range left right)))
  23. (define value
  24. (lambda (seg-tree) (car seg-tree)))
  25. (define range
  26. (lambda (seg-tree) (cadr seg-tree)))
  27. (define left-child
  28. (lambda (seg-tree) (caddr seg-tree)))
  29. (define right-child
  30. (lambda (seg-tree) (cadddr seg-tree)))
  31.  
  32. ;; Create a Range Maximum Query (RMQ) segment tree with all values
  33. ;; initialized to 0.
  34. (define build-empty-segment-tree
  35. ;; Takes an integer n, and returns a segment tree for the range [0, n-1].
  36. ;; All values are initialized to 0.
  37. ;; Ranges are 0 based.
  38. (lambda (n)
  39. (letrec ((B (lambda (cur-range)
  40. (let* ((lo (low cur-range))
  41. (hi (high cur-range))
  42. (mid (floor (/ (+ lo hi) 2)))
  43. (left-range (make-range lo mid))
  44. (right-range (make-range (+ mid 1) hi)))
  45. (if (= lo hi)
  46. (make-segment-tree 0 cur-range '() '())
  47. (make-segment-tree 0 cur-range (B left-range) (B right-range)))))))
  48. (B (make-range 0 (- n 1))))))
  49.  
  50. ;; Create a segment tree for RMQ from a list of integers.
  51. (define build-segment-tree-from-list
  52. ;; Takes a list of integers and returns a segment tree initialized to the values in the list.
  53. (lambda (l)
  54. (letrec ((B (lambda (seg-tree i l)
  55. (if (null? l)
  56. seg-tree
  57. (update-segment-tree (B seg-tree (+ i 1) (cdr l)) i (car l))))))
  58. (B (build-empty-segment-tree (length l)) 0 l))))
  59.  
  60. ;; Update the ith leaf of the segment tree with a new value
  61. (define update-segment-tree
  62. ;; Takes as arguments the index i (0-based) and the new value at ith leaf.
  63. ;; Return the updated segment tree.
  64. (lambda (seg-tree i new-value)
  65. (let* ((cur-range (range seg-tree))
  66. (lo (low cur-range))
  67. (hi (high cur-range))
  68. (left (left-child seg-tree))
  69. (right (right-child seg-tree)))
  70. (cond ((not (integer-inside-range? i cur-range)) seg-tree)
  71. ((= lo hi) (make-segment-tree new-value cur-range left right))
  72. (else (let ((new-left (update-segment-tree left i new-value))
  73. (new-right (update-segment-tree right i new-value)))
  74. (make-segment-tree (max (value new-left) (value new-right))
  75. cur-range
  76. new-left
  77. new-right)))))))
  78.  
  79. ;; Query the maximum value within a range.
  80. (define query-segment-tree
  81. ;; Takes a segment tree and a range and returns the maximum value within
  82. ;; the range.
  83. (lambda (seg-tree query-range)
  84. (let* ((cur-range (range seg-tree))
  85. (lo (low cur-range))
  86. (hi (high cur-range))
  87. (lo-query (low query-range))
  88. (hi-query (high query-range)))
  89. (cond ((or (> lo-query hi) (< hi-query lo)) #f)
  90. ((range-inside-range? cur-range query-range) (value seg-tree))
  91. (else (let ((left-max (query-segment-tree (left-child seg-tree) query-range))
  92. (right-max (query-segment-tree (right-child seg-tree) query-range)))
  93. (cond ((not (number? left-max)) right-max)
  94. ((not (number? right-max)) left-max)
  95. (else (max left-max right-max)))))))))
  96.  
  97. ;; Obtain the values in the leaves of the segment tree
  98. (define leaf-values
  99. ;; Takes a segment tree and returns a list representing
  100. ;; the values in the leaves of the segment tree.
  101. (lambda (seg-tree)
  102. (if (and (null? (left-child seg-tree)) (null? (right-child seg-tree)))
  103. (cons (value seg-tree) '())
  104. (append (leaf-values (left-child seg-tree)) (leaf-values (right-child seg-tree))))))
  105.  
  106. ;; Tests
  107. (define (run-tests)
  108. ;; Build and initialize the tree
  109. (define seg-tree (build-segment-tree-from-list '(4 7 2 9)))
  110. (display (leaf-values seg-tree)) (newline) ; (4 7 2 9)
  111. ;; Queries and updates
  112. (display (query-segment-tree seg-tree (make-range 0 3))) (newline) ; 9
  113. (display (query-segment-tree seg-tree (make-range 1 1))) (newline) ; 7
  114. (display (query-segment-tree seg-tree (make-range 1 2))) (newline) ; 7
  115. (set! seg-tree (update-segment-tree seg-tree 1 5))
  116. (display (leaf-values seg-tree)) (newline) ; (4 5 2 9)
  117. (display (query-segment-tree seg-tree (make-range 1 2))) (newline) ; 5
  118. (display (query-segment-tree seg-tree (make-range 1 3))) (newline) ; 9
  119. (set! seg-tree (update-segment-tree seg-tree 3 100))
  120. (display (leaf-values seg-tree)) (newline) ; (4 5 2 100)
  121. (display (query-segment-tree seg-tree (make-range 0 2))) (newline) ; 5
  122. (display (query-segment-tree seg-tree (make-range 0 3))) (newline) ; 100
  123. 'done)
Add Comment
Please, Sign In to add comment