noya2_Library

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

View the Project on GitHub noya2ruler/noya2_Library

:warning: misc/segment_divide_conquer.hpp

Depends on

Code

#pragma once

#include"data_structure/csr.hpp"

namespace noya2 {

struct segment_divide_conquer {
    int tmax, sz;
    internal::csr<int> events;
    segment_divide_conquer (int _tmax) : tmax(_tmax){
        sz = std::bit_ceil<uint32_t>(tmax);
        events = internal::csr<int>(sz*2);
    }
    void add_event(int tl, int tr, int id){
        tl += sz, tr += sz;
        while (tl < tr){
            if (tl & 1){
                events.add(tl++, id);
            }
            if (tr & 1){
                events.add(--tr, id);
            }
            tl >>= 1;
            tr >>= 1;
        }
    }
    // void apply(int eventid);
    // void rollback(int eventid);
    // void query(int t);
    void run(auto apply, auto rollback, auto query){
        events.build();
        auto dfs = [&](auto sfs, int p) -> void {
            for (int id : events[p]){
                apply(id);
            }
            if (p >= sz){
                p -= sz;
                if (p < tmax){
                    query(p);
                }
                p += sz;
            }
            else {
                sfs(sfs, p * 2);
                sfs(sfs, p * 2 + 1);
            }
            for (int id : events[p] | std::views::reverse){
                rollback(id);
            }
        };
        dfs(dfs,1);
    }
};

} // namespace noya2
#line 2 "misc/segment_divide_conquer.hpp"

#line 2 "data_structure/csr.hpp"

#include<vector>
#include<ranges>
#include<cassert>
#include<utility>

namespace noya2::internal {

template<class E>
struct csr {
    csr () {}
    csr (int _n) : n(_n) {}
    csr (int _n, int m) : n(_n){
        start.reserve(m);
        elist.reserve(m);
    }
    // ACL style constructor (do not have to call build)
    csr (int _n, const std::vector<std::pair<int,E>> &idx_elem) : n(_n), start(_n + 2), elist(idx_elem.size()) {
        for (auto &[i, e] : idx_elem){
            start[i + 2]++;
        }
        for (int i = 1; i < n; i++){
            start[i + 2] += start[i + 1];
        }
        for (auto &[i, e] : idx_elem){
            elist[start[i + 1]++] = e;
        }
        prepared = true;
    }
    int add(int idx, E elem){
        int eid = start.size();
        start.emplace_back(idx);
        elist.emplace_back(elem);
        return eid;
    }
    void build(){
        if (prepared) return ;
        int m = start.size();
        std::vector<E> nelist(m);
        std::vector<int> nstart(n + 2, 0);
        for (int i = 0; i < m; i++){
            nstart[start[i] + 2]++;
        }
        for (int i = 1; i < n; i++){
            nstart[i + 2] += nstart[i + 1];
        }
        for (int i = 0; i < m; i++){
            nelist[nstart[start[i] + 1]++] = elist[i];
        }
        swap(elist,nelist);
        swap(start,nstart);
        prepared = true;
    }
    const auto operator[](int idx) const {
        return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);
    }
    auto operator[](int idx){
        return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);
    }
    const auto operator()(int idx, int l, int r) const {
        return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);
    }
    auto operator()(int idx, int l, int r){
        return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);
    }
    size_t size() const {
        return n;
    }
    int n;
    std::vector<int> start;
    std::vector<E> elist;
    bool prepared = false;
};

} // namespace noya2::internal
#line 4 "misc/segment_divide_conquer.hpp"

namespace noya2 {

struct segment_divide_conquer {
    int tmax, sz;
    internal::csr<int> events;
    segment_divide_conquer (int _tmax) : tmax(_tmax){
        sz = std::bit_ceil<uint32_t>(tmax);
        events = internal::csr<int>(sz*2);
    }
    void add_event(int tl, int tr, int id){
        tl += sz, tr += sz;
        while (tl < tr){
            if (tl & 1){
                events.add(tl++, id);
            }
            if (tr & 1){
                events.add(--tr, id);
            }
            tl >>= 1;
            tr >>= 1;
        }
    }
    // void apply(int eventid);
    // void rollback(int eventid);
    // void query(int t);
    void run(auto apply, auto rollback, auto query){
        events.build();
        auto dfs = [&](auto sfs, int p) -> void {
            for (int id : events[p]){
                apply(id);
            }
            if (p >= sz){
                p -= sz;
                if (p < tmax){
                    query(p);
                }
                p += sz;
            }
            else {
                sfs(sfs, p * 2);
                sfs(sfs, p * 2 + 1);
            }
            for (int id : events[p] | std::views::reverse){
                rollback(id);
            }
        };
        dfs(dfs,1);
    }
};

} // namespace noya2
Back to top page