po167_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub potato167/po167_library

:heavy_check_mark: test/ds/doubling_rmq.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq"

#include "../../ds/Doubling.hpp"

int op(int a, int b){
    return std::min(a, b);
}

#include <iostream>

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int N, Q;
    std::cin >> N >> Q;
    std::vector<int> 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<int, op> D(P, A, N);
    while (Q--){
        int l, r;
        std::cin >> l >> r;
        std::cout << D.query(l, 1 << 30, r - l).val << "\n";
    }
}
#line 1 "test/ds/doubling_rmq.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq"

#line 2 "ds/Doubling.hpp"
#include <vector>
#include <cassert>
namespace po167{

template<class T, T(*op)(T, T)>
struct Doubling_op{
    struct result{
        long long times;
        int ind;
        T val;
    };
    int n;
    int depth;
    std::vector<std::vector<int>> index;
    std::vector<std::vector<T>> val;
    Doubling_op(std::vector<int> p, std::vector<T> 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]);
            }
        }
    }
    result 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;
        long long TIMES = times;
        while (times){
            if (times & 1){
                start_val = op(start_val, val[i][start_ind]);
                start_ind = index[i][start_ind];
            }
            i++;
            times >>= 1;
        }
        return {TIMES, start_ind, start_val};
    }
    result max_right(int start_ind, T start_val, auto f){
        if (!f(start_val)) return {-1, start_ind, start_val};
        long long times = 0;
        for (int d = depth - 1; d >= 0; d--){
            if (f(op(start_val, val[d][start_ind]))){
                start_val = op(start_val, val[d][start_ind]);
                start_ind = index[d][start_ind];
                times += (1ll << d);
            }
        }
        return {times, start_ind, start_val};
    }
};

struct Doubling{
    int n;
    int depth;
    std::vector<std::vector<int>> index;
    Doubling(std::vector<int> 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;
    }
};
}
#line 4 "test/ds/doubling_rmq.test.cpp"

int op(int a, int b){
    return std::min(a, b);
}

#include <iostream>

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int N, Q;
    std::cin >> N >> Q;
    std::vector<int> 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<int, op> D(P, A, N);
    while (Q--){
        int l, r;
        std::cin >> l >> r;
        std::cout << D.query(l, 1 << 30, r - l).val << "\n";
    }
}
Back to top page