Guest User

Untitled

a guest
Feb 18th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.41 KB | None | 0 0
  1. #include <limits>
  2. #include <cmath>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <cstdint>
  6.  
  7. #if __cplusplus >= 201703
  8. #define IF_CONSTEXPR if constexpr
  9. #else
  10. #define IF_CONSTEXPR if
  11. #endif
  12.  
  13. template<class T>
  14. using should_move = std::is_same<T, std::remove_reference_t<T>>; // same trick as std::forward does
  15.  
  16. template<class T>
  17. T&& forward_subpart(T&& value, std::true_type whether_should_move) {
  18. return std::move(value);
  19. }
  20.  
  21. template<class T>
  22. T&& forward_subpart(T&& value, std::false_type whether_should_move) {
  23. return value;
  24. }
  25.  
  26. uint64_t msb64(uint64_t x) {
  27. x |= (x >> 1);
  28. x |= (x >> 2);
  29. x |= (x >> 4);
  30. x |= (x >> 8);
  31. x |= (x >> 16);
  32. x |= (x >> 32);
  33. return x & ~(x >> 1);
  34. }
  35.  
  36. template<class Monoid>
  37. struct SegmentTree {
  38. // This layout is intentional:
  39. // we need the constants to be initialized when constructing store,
  40. // at the same time the overhead incurred by such layout is expected to be
  41. // order of magnitude less than the overall footprint in typical usage.
  42.  
  43. const size_t lowest_layer_idx;
  44. const size_t lowest_layer_begin;
  45. std::vector<Monoid> store;
  46.  
  47. template<class Cont>
  48. SegmentTree(Cont&& cont)
  49. : lowest_layer_idx(std::ceil(std::log2(cont.size())))
  50. , lowest_layer_begin(1 << lowest_layer_idx) // derived from the formula of geometric progression sum; vertexes numbered from 1
  51. , store(lowest_layer_begin << 1) {
  52. IF_CONSTEXPR (should_move<Cont>::value) {
  53. std::move(std::begin(cont), std::end(cont), store.begin() + lowest_layer_begin);
  54. } else {
  55. std::copy(std::begin(cont), std::end(cont), store.begin() + lowest_layer_begin);
  56. }
  57. for (int idx = lowest_layer_begin - 1; idx > 0; --idx) {
  58. store[idx] = Monoid::combine(store[2 * idx], store[2 * idx + 1]);
  59. }
  60. }
  61.  
  62. Monoid query(size_t left, size_t right) { // 1-based numeration, half-open range
  63. if (left < 1 || left >= right || right > lowest_layer_begin * 2) { return Monoid{}; };
  64. left -= 1, right -= 1;
  65. Monoid result;
  66. size_t span;
  67. for (uint64_t subsegment_begin = left; subsegment_begin < right; subsegment_begin += span) {
  68. size_t max_possible_span = (subsegment_begin ? subsegment_begin & -subsegment_begin : std::numeric_limits<size_t>::max());
  69. size_t max_allowed_span = msb64(right - subsegment_begin);
  70. span = std::min(max_possible_span, max_allowed_span);
  71.  
  72. result = Monoid::combine(result, store[(lowest_layer_begin + subsegment_begin) / span]);
  73. }
  74. return result;
  75. }
  76. };
Add Comment
Please, Sign In to add comment