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/waveletmatrix_4.test.cpp

Depends on

Code

#define PROBLEM "https://yukicoder.me/problems/no/878"

#include "../../ds/WaveletMatrix.hpp"
#include <iostream>
#include <vector>

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N, Q;
    std::cin >> N >> Q;
    std::vector<int> A(N);
    for (auto &a : A) std::cin >> a;

    // P[i]: 直前の A[i] より大きい要素の位置(1-indexed、なければ 0)。
    std::vector<int> P(N), st;
    st.reserve(N);
    for (int i = 0; i < N; i++){
        while (!st.empty() && A[st.back()] <= A[i]){
            st.pop_back();
        }
        P[i] = st.empty() ? 0 : st.back() + 1;
        st.push_back(i);
    }

    po167::WaveletMatrix<int> wm(P);
    while (Q--){
        int t, l, r;
        std::cin >> t >> l >> r;
        std::cout << wm.range_freq(l - 1, r, l) << "\n";
    }
}
#line 1 "test/ds/waveletmatrix_4.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/878"

#line 2 "ds/WaveletMatrix.hpp"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <limits>
#include <type_traits>
#include <utility>
#include <vector>

namespace po167{
// Nonnegative integer values; C++17, no required CPU extensions.
// Based on the API at:
// https://nyaannyaan.github.io/library/data-structure-2d/wavelet-matrix.hpp.html
struct bit_vector {
    using u32 = std::uint32_t;
    using u64 = std::uint64_t;
    static constexpr u32 w = 32;

    // Low 32 bits: data. High 32 bits: number of preceding one-bits.
    std::vector<u64> block;
    u32 n = 0, zeros = 0;

    bit_vector(u32 size = 0) { init(size); }
    void init(u32 size) {
        n = zeros = size;
        block.assign(n / w + 1, 0);
    }
    static u32 popcount(u32 x) {
        x -= (x >> 1) & 0x55555555u;
        x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
        x = (x + (x >> 4)) & 0x0f0f0f0fu;
        return u32(x * 0x01010101u) >> 24;
    }
    u32 get(u32 i) const { return (u32(block[i / w]) >> (i % w)) & 1; }
    void set(u32 i) { block[i / w] |= u64(1) << (i % w); }
    void build() {
        u32 sum = 0;
        for (auto& x : block) {
            u32 bits = u32(x);
            x = (u64(sum) << 32) | bits;
            sum += popcount(bits);
        }
        zeros = n - sum;
    }
    u32 rank1(u32 i) const {
        u64 x = block[i / w];
        return u32(x >> 32) + popcount(u32(x) & ((u32(1) << (i % w)) - 1));
    }
    u32 rank0(u32 i) const { return i - rank1(i); }
};

template <typename T, bool FastKth = true>
struct WaveletMatrix {
    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value,
                  "T must be a non-bool integer type");
    using U = typename std::make_unsigned<T>::type;
    using u32 = std::uint32_t;

    int n = 0, lg = 1, mid_h = -1;
    T max_value = 0;
    std::vector<T> a, mid;
    std::vector<bit_vector> bv;

    WaveletMatrix(u32 size) : n(int(size)), a(size) {
        assert(size <= u32((std::numeric_limits<int>::max)()));
    }
    WaveletMatrix(const std::vector<T>& values) : a(values) { build(); }

    void set(u32 i, const T& x) {
        assert(i < a.size() && x >= 0);
        a[i] = x;
    }
    void build() {
        assert(a.size() <= std::size_t((std::numeric_limits<int>::max)()));
        n = int(a.size());
        max_value = 0;
        for (T x : a) {
            assert(x >= 0);
            if (max_value < x) max_value = x;
        }
        lg = 1;
        for (U x = U(max_value); x >>= 1;) ++lg;
        mid.clear();
        mid_h = lg - 2;
        for (u32 x = u32(n); x; x >>= 1) --mid_h;
        bv.assign(lg, bit_vector(u32(n)));
        std::vector<T> cur = a, nxt(n);
        for (int h = lg - 1; h >= 0; --h) {
            // Keep one intermediate order to finish small candidate ranges.
            if constexpr (FastKth) {
                if (h == mid_h) mid = cur;
            }
            auto& b = bv[h];
            for (u32 i = 0; i < u32(n); i += 32) {
                u32 bits = 0, len = (std::min)(u32(32), u32(n) - i);
                for (u32 j = 0; j < len; ++j)
                    bits |= u32((U(cur[i + j]) >> h) & 1) << j;
                b.block[i / 32] = bits;
            }
            b.build();
            if (h == 0) break;
            u32 pos[2] = {0, b.zeros};
            for (T x : cur) nxt[pos[(U(x) >> h) & 1]++] = x;
            cur.swap(nxt);
        }
    }

    std::pair<u32, u32> succ0(int l, int r, int h) const {
        return {bv[h].rank0(l), bv[h].rank0(r)};
    }
    std::pair<u32, u32> succ1(int l, int r, int h) const {
        const auto& b = bv[h];
        return {b.zeros + b.rank1(l), b.zeros + b.rank1(r)};
    }
    T access(u32 k) const {
        assert(k < a.size());
        return a[k];
    }
    T kth_smallest(u32 l, u32 r, u32 k) const {
        assert(l <= r && r <= u32(n) && k < r - l);
        if (r - l == 1) return a[l];
        U res = 0;
        for (int h = lg - 1; h >= 0; --h) {
            if constexpr (FastKth) {
                if (h == mid_h && r - l <= 2)
                    return k ? (std::max)(mid[l], mid[r - 1])
                             : (std::min)(mid[l], mid[r - 1]);
            }
            const auto& b = bv[h];
            u32 l1 = b.rank1(l), r1 = b.rank1(r);
            u32 l0 = l - l1, r0 = r - r1, cnt = r0 - l0;
            bool f = k >= cnt;
            k -= f ? cnt : 0;
            res |= U(f) << h;
            l = f ? b.zeros + l1 : l0;
            r = f ? b.zeros + r1 : r0;
        }
        return T(res);
    }
    T kth_largest(int l, int r, int k) const {
        assert(0 <= k && k < r - l);
        return kth_smallest(l, r, r - l - k - 1);
    }
    int range_freq(int l, int r, T upper) const {
        assert(0 <= l && l <= r && r <= n);
        if (upper <= 0) return 0;
        if (upper > max_value) return r - l;
        u32 ret = 0;
        for (int h = lg - 1; h >= 0 && l < r; --h) {
            const auto& b = bv[h];
            u32 l1 = b.rank1(l), r1 = b.rank1(r);
            u32 l0 = u32(l) - l1, r0 = u32(r) - r1;
            bool f = (U(upper) >> h) & 1;
            ret += f ? r0 - l0 : 0;
            l = int(f ? b.zeros + l1 : l0);
            r = int(f ? b.zeros + r1 : r0);
        }
        return int(ret);
    }
    int range_freq(int l, int r, T lower, T upper) const {
        return lower < upper ? range_freq(l, r, upper) - range_freq(l, r, lower) : 0;
    }
    // Return T(-1) when no such value exists.
    T prev_value(int l, int r, T upper) const {
        int cnt = range_freq(l, r, upper);
        return cnt == 0 ? T(-1) : kth_smallest(l, r, cnt - 1);
    }
    T next_value(int l, int r, T lower) const {
        int cnt = range_freq(l, r, lower);
        return cnt == r - l ? T(-1) : kth_smallest(l, r, cnt);
    }
};
}
#line 4 "test/ds/waveletmatrix_4.test.cpp"
#include <iostream>
#line 6 "test/ds/waveletmatrix_4.test.cpp"

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N, Q;
    std::cin >> N >> Q;
    std::vector<int> A(N);
    for (auto &a : A) std::cin >> a;

    // P[i]: 直前の A[i] より大きい要素の位置(1-indexed、なければ 0)。
    std::vector<int> P(N), st;
    st.reserve(N);
    for (int i = 0; i < N; i++){
        while (!st.empty() && A[st.back()] <= A[i]){
            st.pop_back();
        }
        P[i] = st.empty() ? 0 : st.back() + 1;
        st.push_back(i);
    }

    po167::WaveletMatrix<int> wm(P);
    while (Q--){
        int t, l, r;
        std::cin >> t >> l >> r;
        std::cout << wm.range_freq(l - 1, r, l) << "\n";
    }
}
Back to top page