This documentation is automatically generated by online-judge-tools/verification-helper
#include "math/stern_brocot_tree.hpp"頂点 $(p, q, r, s)$ は $\frac{p+r}{q+s}$ に対応する
vector<T> sbt::encode_path<T>(a, b) : $\frac{a}{b}$ に対応する頂点までのパスを連長圧縮したものを取得。0-indexed で偶数番目が左方向, 奇数番目が右方向への移動を示す。 $O(\log \max(a, b))$tuple<T, T, T, T> sbt::decode_path<T>(vector<T> path) : path に対応する頂点を取得 $O(\log \max(p, q, r, s))$tuple<T, T, T, T> sbt::lca<T>(T p, T q, T r, T s) : $\frac{p}{q}$ と $\frac{r}{s}$ に対応する頂点の LCA を求める。$O(\log \max(p, q, r, s))$tuple<T, T, T, T> sbt::ancestor(T p, T q, T d) : $\frac{p}{q}$ に対応する頂点から $d$ 個祖先の頂点を求める。 $O(\log \max(p, q, r, s))$tuple<T, T, T, T> sbt::range(T p, T q) : $\frac{p}{q}$ に対応する頂点の子孫の下限と上限を求める。$O(\log \max(p, q, r, s))$#pragma once
#include<algorithm>
#include<optional>
#include<ranges>
#include<tuple>
#include<vector>
namespace sbt{
template<class T>
std::tuple<T, T, T, T> child(T p, T q, T r, T s, T d, bool is_left){
if(is_left){
r += d*p;
s += d*q;
}else{
p += d*r;
q += d*s;
}
return std::make_tuple(p, q, r, s);
}
template<class T>
std::tuple<T, T, T, T> parent(T p, T q, T r, T s){
if(p == 0 && q == 1 && r == 1 && s == 0){
return std::make_tuple(0, 0, 0, 0);
}
if(p < r || q < s){
r -= p, s -= q;
}else{
p -= r, q -= s;
}
return std::make_tuple(p, q, r, s);
}
template<class T>
std::vector<T> encode_path(T p, T q){
std::vector<T> a;
if(p < q){
a.emplace_back(0);
std::swap(p, q);
}
while(p != 1){
a.emplace_back(p/q);
p %= q;
std::swap(p, q);
}
if(not a.empty()){
if(a.back() == 1){
a.pop_back();
}else{
a.back()--;
}
}
return a;
}
template<class T>
std::tuple<T, T, T, T> decode_path(const std::vector<T> &a){
T p = 0, q = 1, r = 1, s = 0;
for(int i = 0;i < std::ssize(a);i++){
std::tie(p, q, r, s) = child(p, q, r, s, a[i], i&1);
}
return std::make_tuple(p, q, r, s);
}
template<class T>
std::tuple<T, T, T, T> lca(T p, T q, T r, T s){
std::vector<T> a = encode_path(p, q), b = encode_path(r, s);
int n = std::min(std::ssize(a), std::ssize(b));
T P = 0, Q = 1, R = 1, S = 0;
for(int i = 0;i < n;i++){
T c = std::min(a[i], b[i]);
std::tie(P, Q, R, S) = child(P, Q, R, S, c, i&1);
if(a[i] != b[i])break;
}
return std::make_tuple(P, Q, R, S);
}
template<class T>
std::optional<std::tuple<T, T, T, T>> ancestor(T p, T q, T d){
std::vector<T> a = encode_path(p, q);
T P = 0, Q = 1, R = 1, S = 0;
for(int i = 0;i < std::ssize(a);i++){
T c = std::min(d, a[i]);
std::tie(P, Q, R, S) = child(P, Q, R, S, c, i&1);
d -= c;
if(d == 0)break;
}
if(d == 0){
return std::make_tuple(P, Q, R, S);
}
return std::nullopt;
}
template<class T>
std::tuple<T, T, T, T> range(T p, T q){
return decode_path(encode_path(p, q));
}
}#line 2 "math/stern_brocot_tree.hpp"
#include<algorithm>
#include<optional>
#include<ranges>
#include<tuple>
#include<vector>
namespace sbt{
template<class T>
std::tuple<T, T, T, T> child(T p, T q, T r, T s, T d, bool is_left){
if(is_left){
r += d*p;
s += d*q;
}else{
p += d*r;
q += d*s;
}
return std::make_tuple(p, q, r, s);
}
template<class T>
std::tuple<T, T, T, T> parent(T p, T q, T r, T s){
if(p == 0 && q == 1 && r == 1 && s == 0){
return std::make_tuple(0, 0, 0, 0);
}
if(p < r || q < s){
r -= p, s -= q;
}else{
p -= r, q -= s;
}
return std::make_tuple(p, q, r, s);
}
template<class T>
std::vector<T> encode_path(T p, T q){
std::vector<T> a;
if(p < q){
a.emplace_back(0);
std::swap(p, q);
}
while(p != 1){
a.emplace_back(p/q);
p %= q;
std::swap(p, q);
}
if(not a.empty()){
if(a.back() == 1){
a.pop_back();
}else{
a.back()--;
}
}
return a;
}
template<class T>
std::tuple<T, T, T, T> decode_path(const std::vector<T> &a){
T p = 0, q = 1, r = 1, s = 0;
for(int i = 0;i < std::ssize(a);i++){
std::tie(p, q, r, s) = child(p, q, r, s, a[i], i&1);
}
return std::make_tuple(p, q, r, s);
}
template<class T>
std::tuple<T, T, T, T> lca(T p, T q, T r, T s){
std::vector<T> a = encode_path(p, q), b = encode_path(r, s);
int n = std::min(std::ssize(a), std::ssize(b));
T P = 0, Q = 1, R = 1, S = 0;
for(int i = 0;i < n;i++){
T c = std::min(a[i], b[i]);
std::tie(P, Q, R, S) = child(P, Q, R, S, c, i&1);
if(a[i] != b[i])break;
}
return std::make_tuple(P, Q, R, S);
}
template<class T>
std::optional<std::tuple<T, T, T, T>> ancestor(T p, T q, T d){
std::vector<T> a = encode_path(p, q);
T P = 0, Q = 1, R = 1, S = 0;
for(int i = 0;i < std::ssize(a);i++){
T c = std::min(d, a[i]);
std::tie(P, Q, R, S) = child(P, Q, R, S, c, i&1);
d -= c;
if(d == 0)break;
}
if(d == 0){
return std::make_tuple(P, Q, R, S);
}
return std::nullopt;
}
template<class T>
std::tuple<T, T, T, T> range(T p, T q){
return decode_path(encode_path(p, q));
}
}