diff --git a/ds/Doubling.hpp b/ds/Doubling.hpp new file mode 100644 index 0000000..aaa4df7 --- /dev/null +++ b/ds/Doubling.hpp @@ -0,0 +1,78 @@ +#pragma once +#include +#include +namespace po167{ + +template +struct Doubling_op{ + int n; + int depth; + std::vector> index; + std::vector> val; + Doubling_op(std::vector p, std::vector v, long long lim = (1ll << 60) - 1){ + n = p.size(); + for (auto x : p) assert(0 <= x && x < n); + assert(n == (int)v.size()); + depth = 1; + while ((1ll << depth) <= lim) depth++; + index.resize(depth); + val.resize(depth); + index[0] = p; + val[0] = v; + for (int i = 1; i < depth; i++){ + index[i].resize(n); + val[i].resize(n); + for (int j = 0; j < n; j++){ + int tmp = index[i - 1][j]; + index[i][j] = index[i - 1][tmp]; + val[i][j] = op(val[i - 1][j], val[i - 1][tmp]); + } + } + } + std::pair query(int start_ind, T start_val, long long times){ + assert(0 <= start_ind && start_ind < n); + assert(0 <= times && times < (1ll << depth)); + int i = 0; + while (times){ + if (times & 1){ + start_val = op(start_val, val[i][start_ind]); + start_ind = index[i][start_ind]; + } + i++; + times >>= 1; + } + return std::make_pair(start_ind, start_val); + } +}; + +struct Doubling{ + int n; + int depth; + std::vector> index; + Doubling(std::vector p, long long lim = (1ll << 60) - 1){ + n = p.size(); + for (auto x : p) assert(0 <= x && x < n); + depth = 1; + while ((1ll << depth) <= lim) depth++; + index.resize(depth); + index[0] = p; + for (int i = 1; i < depth; i++){ + index[i].resize(n); + for (int j = 0; j < n; j++){ + index[i][j] = index[i - 1][index[i - 1][j]]; + } + } + } + int query(int ind, long long times){ + assert(0 <= ind && ind < n); + assert(0 <= times && times < (1ll << depth)); + int i = 0; + while (times){ + if (times & 1) ind = index[i][ind]; + i++; + times >>= 1; + } + return ind; + } +}; +} diff --git a/test/ds/doubling_rmq.test.cpp b/test/ds/doubling_rmq.test.cpp new file mode 100644 index 0000000..87294cb --- /dev/null +++ b/test/ds/doubling_rmq.test.cpp @@ -0,0 +1,27 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" + +#include "../../ds/Doubling.hpp" + +int op(int a, int b){ + return std::min(a, b); +} + +#include + +int main(){ + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + int N, Q; + std::cin >> N >> Q; + std::vector A(N), P(N); + for (int i = 0; i < N; i++){ + std::cin >> A[i]; + P[i] = std::min(i + 1, N - 1); + } + po167::Doubling_op D(P, A, N); + while (Q--){ + int l, r; + std::cin >> l >> r; + std::cout << D.query(l, 1 << 30, r - l).second << "\n"; + } +} \ No newline at end of file