Guest User

Problem I Segment Tree

a guest
Aug 17th, 2025
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.26 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cstdint>
  3. #include <ios>
  4. #include <iostream>
  5. #include <map>
  6. #include <numeric>
  7. #include <utility>
  8. #include <vector>
  9.  
  10. namespace segment_tree {
  11.  
  12.     constexpr std::int32_t log_2(std::int32_t);
  13.  
  14.     template <typename F>
  15.     void for_pars(std::int32_t nd, std::int32_t dir, F f) {
  16.  
  17.         const std::int32_t lvls = log_2(nd);
  18.  
  19.         for (std::int32_t i = 1; i <= lvls; ++i) {
  20.             f(nd >> (dir == 0 ? lvls - i + 1 : i));
  21.         }
  22.  
  23.     }
  24.  
  25.     template <typename F>
  26.     void for_rng(std::int32_t nd_l, std::int32_t nd_r, F f) {
  27.  
  28.         while (nd_l < nd_r) {
  29.             if (nd_l & 1) {
  30.                 f(nd_l);
  31.                 ++nd_l;
  32.             }
  33.             if (nd_r & 1) {
  34.                 --nd_r;
  35.                 f(nd_r);
  36.             }
  37.             nd_l >>= 1;
  38.             nd_r >>= 1;
  39.         }
  40.  
  41.     }
  42.  
  43.     template <typename F>
  44.     void for_rng_ord(std::int32_t nd_l, std::int32_t nd_r, F f) {
  45.  
  46.         if (nd_r - nd_l <= 0) {
  47.             return;
  48.         }
  49.  
  50.         const std::int32_t msk = (1 << log_2((nd_l - 1) ^ nd_r)) - 1;
  51.  
  52.         std::int32_t nd = -nd_l & msk;
  53.  
  54.         while (nd) {
  55.             const std::int32_t bit = __builtin_ctz(nd);
  56.             f(((nd_l - 1) >> bit) + 1);
  57.             nd ^= 1 << bit;
  58.         }
  59.  
  60.         nd = nd_r & msk;
  61.  
  62.         while (nd) {
  63.             const std::int32_t bit = log_2(nd);
  64.             f((nd_r >> bit) - 1);
  65.             nd ^= 1 << bit;
  66.         }
  67.  
  68.     }
  69.  
  70.     constexpr std::int32_t log_2(std::int32_t x) {
  71.  
  72.         return 31 - __builtin_clz(x);
  73.  
  74.     }
  75.  
  76. }
  77.  
  78. template <typename F>
  79. class y_combinator {
  80.  
  81. private:
  82.  
  83.     F f;
  84.  
  85. public:
  86.  
  87.     explicit y_combinator(F&& f) : f(f) {}
  88.  
  89.     template <typename... Args>
  90.     decltype(auto) operator()(Args&&... args) const {
  91.  
  92.         return f(*this, std::forward<Args>(args)...);
  93.  
  94.     }
  95.  
  96. };
  97.  
  98. template <typename F>
  99. y_combinator(F) -> y_combinator<F>;
  100.  
  101. void solve() {
  102.  
  103.     std::int32_t n;
  104.     std::int32_t q;
  105.  
  106.     std::cin >> n >> q;
  107.  
  108.     std::vector<std::int32_t> a(n);
  109.  
  110.     for (auto& x : a) {
  111.         std::cin >> x;
  112.     }
  113.  
  114.     const std::int32_t inf = *std::max_element(std::begin(a), std::end(a)) + n;
  115.     std::map<std::int32_t, std::int32_t> nxts;
  116.     const std::int32_t seg_sz = 1 << segment_tree::log_2(n * 2 - 1);
  117.  
  118.     std::vector seg(seg_sz * 2, inf);
  119.     std::vector seg_apps(seg_sz * 2, inf);
  120.     std::vector seg_bnds(seg_sz * 2, n);
  121.     std::vector<std::int32_t> seg_idxs(seg_sz * 2);
  122.     std::vector<std::int32_t> seg_mxs(seg_sz * 2);
  123.     std::vector<std::int32_t> szs(seg_sz * 2);
  124.  
  125.     std::copy(std::begin(a), std::end(a), std::begin(seg_mxs) + seg_sz);
  126.  
  127.     for (std::int32_t i = 0; i < n; ++i) {
  128.         seg[seg_sz + i] = a[i] - i;
  129.     }
  130.  
  131.     std::iota(std::begin(seg_idxs) + seg_sz, std::end(seg_idxs), 0);
  132.  
  133.     std::fill_n(std::begin(szs) + seg_sz, n, 1);
  134.  
  135.     for (std::int32_t i = n - 1; i >= 0; --i) {
  136.         if (nxts.count(a[i])) {
  137.             seg_bnds[seg_sz + i] = nxts[a[i]];
  138.         }
  139.         nxts[a[i]] = i;
  140.     }
  141.  
  142.     const auto apply = [&](std::int32_t nd, std::int32_t mx) -> std::int32_t {
  143.         if (seg_mxs[nd] <= mx) {
  144.             return mx - seg_idxs[nd];
  145.         }
  146.         std::int32_t res = inf;
  147.         y_combinator(
  148.             [&](auto self, std::int32_t seg_nd) -> void {
  149.                 if (seg_nd >= seg_sz) {
  150.                     res = std::min(res, seg[seg_nd]);
  151.                     return;
  152.                 }
  153.                 const std::int32_t nd_l = seg_nd << 1;
  154.                 const std::int32_t nd_r = seg_nd << 1 | 1;
  155.                 if (seg_mxs[nd_l] > mx) {
  156.                     self(nd_l);
  157.                     res = std::min(res, seg_apps[seg_nd]);
  158.                 } else {
  159.                     res = std::min(res, mx - seg_idxs[nd_l]);
  160.                     self(nd_r);
  161.                 }
  162.             }
  163.         )(nd);
  164.         return res;
  165.     };
  166.  
  167.     for (std::int32_t i = seg_sz - 1; i; --i) {
  168.         seg_mxs[i] = std::max(seg_mxs[i << 1], seg_mxs[i << 1 | 1]);
  169.         seg_idxs[i] = seg_idxs[i << 1 | 1];
  170.         szs[i] = szs[i << 1] + szs[i << 1 | 1];
  171.         seg_apps[i] = apply(i << 1 | 1, seg_mxs[i << 1]);
  172.         seg[i] = std::min(seg[i << 1], seg_apps[i]);
  173.         seg_bnds[i] = std::min(seg_bnds[i << 1], seg_bnds[i << 1 | 1]);
  174.     }
  175.  
  176.     for (std::int32_t i = 0; i < q; ++i) {
  177.         std::int32_t l;
  178.         std::int32_t r;
  179.         std::cin >> l >> r;
  180.         --l;
  181.         --r;
  182.         std::int32_t bnd = r + 1;
  183.         std::int32_t mx = 0;
  184.         std::int32_t val;
  185.         segment_tree::for_rng(
  186.             seg_sz + l, seg_sz + r + 1,
  187.             [&](std::int32_t nd) -> void {
  188.                 bnd = std::min(bnd, seg_bnds[nd]);
  189.             }
  190.         );
  191.         segment_tree::for_rng_ord(
  192.             seg_sz + l, seg_sz + bnd,
  193.             [&](std::int32_t nd) -> void {
  194.                 if (mx) {
  195.                     val = std::min(val, apply(nd, mx));
  196.                 } else {
  197.                     val = seg[nd];
  198.                 }
  199.                 mx = std::max(mx, seg_mxs[nd]);
  200.             }
  201.         );
  202.         val += l - 1;
  203.         std::cout << val << '\n';
  204.     }
  205.  
  206. }
  207.  
  208. int main() {
  209.  
  210.     std::cin.tie(nullptr);
  211.  
  212.     std::ios_base::sync_with_stdio(false);
  213.  
  214.     solve();
  215.  
  216.     return 0;
  217.  
  218. }
  219.  
Advertisement
Add Comment
Please, Sign In to add comment