serna37's Library

Logo

C++ アルゴリズムとデータ構造のライブラリ

View the Project on GitHub serna37/library-cpp

:heavy_check_mark: Segment Tree
(library/segtree/segment_tree.hpp)

Segment Tree

詳しい説明

できること

計算量

使い方

SegmentTree<int> seg(Monoid::Min::op, Monoid::Min::e, N);

Depends on

Required by

Verified with

Code

#pragma once
#include <functional>
#include "library/various/monoid.hpp"
template <typename T> struct SegmentTree {
    using F = function<T(T, T)>;

  private:
    F op;
    T e;
    int N, size, log = 1;
    vector<T> node;
    void init() {
        while ((1ll << log) < N) ++log;
        node.assign((size = 1ll << log) << 1, e);
    }

  public:
    SegmentTree(F op, T e, int N) : op(op), e(e), N(N) { init(); }
    SegmentTree(F op, T e, const vector<T> &A) : op(op), e(e), N(A.size()) {
        init();
        for (int i = 0; i < N; ++i) node[i + size] = A[i];
        for (int i = size - 1; i >= 1; --i)
            node[i] = op(node[i << 1 | 0], node[i << 1 | 1]);
    }
    void set(int i, const T &x) {
        node[i += size] = x;
        while (i >>= 1) node[i] = op(node[i << 1 | 0], node[i << 1 | 1]);
    }
    T prod(int l, int r) {
        T L = e, R = e;
        for (l += size, r += size; l < r; l >>= 1, r >>= 1) {
            if (l & 1) L = op(L, node[l++]);
            if (r & 1) R = op(node[--r], R);
        }
        return op(L, R);
    }
};
#line 2 "library/segtree/segment_tree.hpp"
#include <functional>
#line 2 "library/various/monoid.hpp"
/**
 * @brief モノイド
 */
struct Monoid {
    // 最小値
    struct Min {
        static constexpr int e = INT_MAX;
        static int op(int x, int y) { return min(x, y); }
    };
    // 最大値
    struct Max {
        static constexpr int e = -INT_MAX;
        static int op(int x, int y) { return max(x, y); }
    };
    // 加算
    struct Add {
        static constexpr int e = 0;
        static int op(int x, int y) { return x + y; }
    };
    // 乗算
    struct Mul {
        static constexpr int e = 1;
        static int op(int x, int y) { return x * y; }
    };
    // 代入
    struct Set {
        static constexpr int e = INT_MAX;
        static int op(int x, int y) { return y == INT_MAX ? x : y; }
    };
    // 最大公約数
    struct Gcd {
        static constexpr int e = 0;
        static int op(int x, int y) { return gcd(x, y); }
    };
    // 最小公倍数
    struct Lcm {
        static constexpr int e = 1;
        static int op(int x, int y) { return lcm(x, y); }
    };
    // 排他的論理和
    struct Xor {
        static constexpr int e = 0;
        static int op(int x, int y) { return x ^ y; }
    };
};
#line 4 "library/segtree/segment_tree.hpp"
template <typename T> struct SegmentTree {
    using F = function<T(T, T)>;

  private:
    F op;
    T e;
    int N, size, log = 1;
    vector<T> node;
    void init() {
        while ((1ll << log) < N) ++log;
        node.assign((size = 1ll << log) << 1, e);
    }

  public:
    SegmentTree(F op, T e, int N) : op(op), e(e), N(N) { init(); }
    SegmentTree(F op, T e, const vector<T> &A) : op(op), e(e), N(A.size()) {
        init();
        for (int i = 0; i < N; ++i) node[i + size] = A[i];
        for (int i = size - 1; i >= 1; --i)
            node[i] = op(node[i << 1 | 0], node[i << 1 | 1]);
    }
    void set(int i, const T &x) {
        node[i += size] = x;
        while (i >>= 1) node[i] = op(node[i << 1 | 0], node[i << 1 | 1]);
    }
    T prod(int l, int r) {
        T L = e, R = e;
        for (l += size, r += size; l < r; l >>= 1, r >>= 1) {
            if (l & 1) L = op(L, node[l++]);
            if (r & 1) R = op(node[--r], R);
        }
        return op(L, R);
    }
};
Back to top page