Skip to content

Commit 81756b5

Browse files
committed
doubling
1 parent 34d5352 commit 81756b5

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

ds/Doubling.hpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#pragma once
2+
#include <vector>
3+
#include <cassert>
4+
namespace po167{
5+
6+
template<class T, T(*op)(T, T)>
7+
struct Doubling_op{
8+
int n;
9+
int depth;
10+
std::vector<std::vector<int>> index;
11+
std::vector<std::vector<T>> val;
12+
Doubling_op(std::vector<int> p, std::vector<T> v, long long lim = (1ll << 60) - 1){
13+
n = p.size();
14+
for (auto x : p) assert(0 <= x && x < n);
15+
assert(n == (int)v.size());
16+
depth = 1;
17+
while ((1ll << depth) <= lim) depth++;
18+
index.resize(depth);
19+
val.resize(depth);
20+
index[0] = p;
21+
val[0] = v;
22+
for (int i = 1; i < depth; i++){
23+
index[i].resize(n);
24+
val[i].resize(n);
25+
for (int j = 0; j < n; j++){
26+
int tmp = index[i - 1][j];
27+
index[i][j] = index[i - 1][tmp];
28+
val[i][j] = op(val[i - 1][j], val[i - 1][tmp]);
29+
}
30+
}
31+
}
32+
std::pair<int, T> query(int start_ind, T start_val, long long times){
33+
assert(0 <= start_ind && start_ind < n);
34+
assert(0 <= times && times < (1ll << depth));
35+
int i = 0;
36+
while (times){
37+
if (times & 1){
38+
start_val = op(start_val, val[i][start_ind]);
39+
start_ind = index[i][start_ind];
40+
}
41+
i++;
42+
times >>= 1;
43+
}
44+
return std::make_pair(start_ind, start_val);
45+
}
46+
};
47+
48+
struct Doubling{
49+
int n;
50+
int depth;
51+
std::vector<std::vector<int>> index;
52+
Doubling(std::vector<int> p, long long lim = (1ll << 60) - 1){
53+
n = p.size();
54+
for (auto x : p) assert(0 <= x && x < n);
55+
depth = 1;
56+
while ((1ll << depth) <= lim) depth++;
57+
index.resize(depth);
58+
index[0] = p;
59+
for (int i = 1; i < depth; i++){
60+
index[i].resize(n);
61+
for (int j = 0; j < n; j++){
62+
index[i][j] = index[i - 1][index[i - 1][j]];
63+
}
64+
}
65+
}
66+
int query(int ind, long long times){
67+
assert(0 <= ind && ind < n);
68+
assert(0 <= times && times < (1ll << depth));
69+
int i = 0;
70+
while (times){
71+
if (times & 1) ind = index[i][ind];
72+
i++;
73+
times >>= 1;
74+
}
75+
return ind;
76+
}
77+
};
78+
}

test/ds/doubling_rmq.test.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq"
2+
3+
#include "../../ds/Doubling.hpp"
4+
5+
int op(int a, int b){
6+
return std::min(a, b);
7+
}
8+
9+
#include <iostream>
10+
11+
int main(){
12+
std::ios::sync_with_stdio(false);
13+
std::cin.tie(nullptr);
14+
int N, Q;
15+
std::cin >> N >> Q;
16+
std::vector<int> A(N), P(N);
17+
for (int i = 0; i < N; i++){
18+
std::cin >> A[i];
19+
P[i] = std::min(i + 1, N - 1);
20+
}
21+
po167::Doubling_op<int, op> D(P, A, N);
22+
while (Q--){
23+
int l, r;
24+
std::cin >> l >> r;
25+
std::cout << D.query(l, 1 << 30, r - l).second << "\n";
26+
}
27+
}

0 commit comments

Comments
 (0)