m1une's library

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

View on GitHub

:heavy_check_mark: Range OR Range Sum
(acted_monoid/range_or_range_sum.hpp)

Overview

An Acted Monoid representing Range Bitwise OR operations and Range Sum queries.

Mathematical Mechanism

Because Bitwise OR does not distribute directly over addition, the node must track how many times each individual bit is set within its range. When a Range OR is applied with a value $f$, any bit set to 1 in $f$ forces that specific bit to become 1 for every element in the segment. Its bit count immediately becomes equal to size.

Template Parameters

Interface and Complexity

This is a stateless acted-monoid tag. Lazy data structures use its public value_type, operator_type, id(), op(a, b), op_id(), op_comp(f, g), and mapping(f, x) members. Helpers such as make(...), shifted mappings, or reversal-aware mappings are described above when the header provides them.

The static operations are $O(1)$ for the scalar metadata stored by these range acted monoids, aside from the cost of the underlying arithmetic type.

Verified with

Code

#ifndef M1UNE_ACTED_MONOID_RANGE_OR_RANGE_SUM_HPP
#define M1UNE_ACTED_MONOID_RANGE_OR_RANGE_SUM_HPP 1

#include <array>

namespace m1une {
namespace acted_monoid {

template <typename T, int BITS = 30>
struct RangeOrRangeSumNode {
    T sum;
    std::array<int, BITS> bit_count;
    long long size;
};

// Acted Monoid for Range OR updates and Range Sum queries.
template <typename T, int BITS = 30>
struct RangeOrRangeSum {
    using value_type = RangeOrRangeSumNode<T, BITS>;
    using operator_type = T;
    static constexpr bool commutative = true;
    static constexpr bool operator_commutative = true;

    static constexpr value_type id() {
        value_type res;
        res.sum = T(0);
        res.bit_count.fill(0);
        res.size = 0;
        return res;
    }

    static constexpr value_type op(const value_type& a, const value_type& b) {
        value_type res;
        res.sum = a.sum + b.sum;
        res.size = a.size + b.size;
        for (int i = 0; i < BITS; ++i) {
            res.bit_count[i] = a.bit_count[i] + b.bit_count[i];
        }
        return res;
    }

    static constexpr operator_type op_id() {
        return T(0);
    }

    static constexpr operator_type op_comp(const operator_type& f, const operator_type& g) {
        return f | g;
    }

    static constexpr value_type mapping(const operator_type& f, const value_type& x) {
        if (f == T(0) || x.size == 0) return x;
        value_type res = x;
        res.sum = T(0);
        for (int i = 0; i < BITS; ++i) {
            if ((f >> i) & 1) {
                res.bit_count[i] = x.size;  // OR forces the bit to be 1 for all elements
            }
            res.sum += static_cast<T>(res.bit_count[i]) * (T(1) << i);
        }
        return res;
    }

    static constexpr value_type make(const T& val) {
        value_type res;
        res.sum = val;
        res.size = 1;
        for (int i = 0; i < BITS; ++i) {
            res.bit_count[i] = ((val >> i) & 1) ? 1 : 0;
        }
        return res;
    }
};

}  // namespace acted_monoid
}  // namespace m1une

#endif  // M1UNE_ACTED_MONOID_RANGE_OR_RANGE_SUM_HPP
#line 1 "acted_monoid/range_or_range_sum.hpp"



#include <array>

namespace m1une {
namespace acted_monoid {

template <typename T, int BITS = 30>
struct RangeOrRangeSumNode {
    T sum;
    std::array<int, BITS> bit_count;
    long long size;
};

// Acted Monoid for Range OR updates and Range Sum queries.
template <typename T, int BITS = 30>
struct RangeOrRangeSum {
    using value_type = RangeOrRangeSumNode<T, BITS>;
    using operator_type = T;
    static constexpr bool commutative = true;
    static constexpr bool operator_commutative = true;

    static constexpr value_type id() {
        value_type res;
        res.sum = T(0);
        res.bit_count.fill(0);
        res.size = 0;
        return res;
    }

    static constexpr value_type op(const value_type& a, const value_type& b) {
        value_type res;
        res.sum = a.sum + b.sum;
        res.size = a.size + b.size;
        for (int i = 0; i < BITS; ++i) {
            res.bit_count[i] = a.bit_count[i] + b.bit_count[i];
        }
        return res;
    }

    static constexpr operator_type op_id() {
        return T(0);
    }

    static constexpr operator_type op_comp(const operator_type& f, const operator_type& g) {
        return f | g;
    }

    static constexpr value_type mapping(const operator_type& f, const value_type& x) {
        if (f == T(0) || x.size == 0) return x;
        value_type res = x;
        res.sum = T(0);
        for (int i = 0; i < BITS; ++i) {
            if ((f >> i) & 1) {
                res.bit_count[i] = x.size;  // OR forces the bit to be 1 for all elements
            }
            res.sum += static_cast<T>(res.bit_count[i]) * (T(1) << i);
        }
        return res;
    }

    static constexpr value_type make(const T& val) {
        value_type res;
        res.sum = val;
        res.size = 1;
        for (int i = 0; i < BITS; ++i) {
            res.bit_count[i] = ((val >> i) & 1) ? 1 : 0;
        }
        return res;
    }
};

}  // namespace acted_monoid
}  // namespace m1une
Back to top page