Library

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

View the Project on GitHub ebi-fly13/Library

:heavy_check_mark: offline 2D segtree
(data_structure/offline_segtree_2d.hpp)

説明

可換モノイドについて、1点更新、長方形領域クエリを行えるデータ構造。クエリ先読みにより、必要な部分だけ作ることでメモリ使用量を減らして点の座標が$10^9$とかでも使える。

offline_segtree_2d<S, op, e, data_structure> seg2d;

S, op, eは可換モノイド、data_structureには以下を要求する

これを満たすデータ構造ならなんでもok (segtree、fenwick treeなどなど)

pre_set(i, j)

$(i,j)$ を追加する。

build()

クエリ先読み後(pre_set後)、セグ木を構築する。

set(i, j, x)

$(i, j)$ を $x$ に更新する。O(\log H)

get(i, j)

$(i, j)$ の値を返す。 $O(1)$

prod(l, d, r, u)

$[l, r) \times [d, u)$ の領域に対してクエリを処理する $O(\log H \log W)$

Depends on

Verified with

Code

#pragma once

#include <algorithm>
#include <vector>

/*
    reference: https://blog.hamayanhamayan.com/entry/2017/12/09/015937
    verify   : http://codeforces.com/contest/893/submission/125531718
*/

#include "../data_structure/compress.hpp"

namespace ebi {

template <class S, S (*op)(S, S), S (*e)(), class data_structure>
struct offline_segtree_2d {
    offline_segtree_2d() = default;

    void pre_set(std::pair<int, int> p) {
        ps.emplace_back(p);
    }

    void build() {
        for (auto [x, y] : ps) {
            xs.add(x);
        }
        xs.build();
        while (sz < xs.size()) sz <<= 1;
        ys.resize(2 * sz);
        for (auto [x, y] : ps) {
            int i = xs.get(x) + sz;
            ys[i].add(y);
            while (i > 1) {
                i >>= 1;
                ys[i].add(y);
            }
        }
        for (int i = 0; i < 2 * sz; i++) {
            ys[i].build();
            data.emplace_back(data_structure(ys[i].size()));
        }
    }

    void set(int i, int j, S val) {
        i = xs.get(i);
        i += sz;
        data[i].set(ys[i].get(j), val);
        while (i > 1) {
            i >>= 1;
            S res = e();
            if (ys[2 * i].find(j)) {
                res = op(res, data[2 * i].get(ys[2 * i].get(j)));
            }
            if (ys[2 * i + 1].find(j)) {
                res = op(res, data[2 * i + 1].get(ys[2 * i + 1].get(j)));
            }
            data[i].set(ys[i].get(j), res);
        }
    }

    S get(int i, int j) const {
        i = xs.get(i) + sz;
        return data[i].get(ys[i].get(j));
    }

    S prod(int l, int d, int r, int u) const {
        l = xs.get(l) + sz;
        r = xs.get(r) + sz;
        S res = e();
        while (l < r) {
            if (l & 1) {
                res = op(res, data[l].prod(ys[l].get(d), ys[l].get(u)));
                l++;
            }
            if (r & 1) {
                r--;
                res = op(data[r].prod(ys[r].get(d), ys[r].get(u)), res);
            }
            l >>= 1;
            r >>= 1;
        }
        return res;
    }

  private:
    int sz = 1;
    std::vector<std::pair<int, int>> ps;
    compress<int> xs;
    std::vector<compress<int>> ys;
    std::vector<data_structure> data;
};

}  // namespace ebi
#line 2 "data_structure/offline_segtree_2d.hpp"

#include <algorithm>
#include <vector>

/*
    reference: https://blog.hamayanhamayan.com/entry/2017/12/09/015937
    verify   : http://codeforces.com/contest/893/submission/125531718
*/

#line 2 "data_structure/compress.hpp"

#line 4 "data_structure/compress.hpp"
#include <cassert>
#line 6 "data_structure/compress.hpp"

namespace ebi {

template <class T> struct compress {
  private:
    std::vector<T> cp;

  public:
    compress() = default;

    compress(std::vector<T> cp_) : cp(cp_) {
        build();
    }

    void build() {
        std::sort(cp.begin(), cp.end());
        cp.erase(std::unique(cp.begin(), cp.end()), cp.end());
    }

    void add(const T &val) {
        cp.emplace_back(val);
    }

    int get(const T &val) const {
        return std::lower_bound(cp.begin(), cp.end(), val) - cp.begin();
    }

    int size() const {
        return cp.size();
    }

    bool find(const T &val) const {
        auto itr = std::lower_bound(cp.begin(), cp.end(), val);
        if (itr == cp.end())
            return false;
        else
            return *itr == val;
    }

    T val(int idx) const {
        assert(0 <= idx && idx < (int)cp.size());
        return cp[idx];
    }
};

}  // namespace ebi
#line 12 "data_structure/offline_segtree_2d.hpp"

namespace ebi {

template <class S, S (*op)(S, S), S (*e)(), class data_structure>
struct offline_segtree_2d {
    offline_segtree_2d() = default;

    void pre_set(std::pair<int, int> p) {
        ps.emplace_back(p);
    }

    void build() {
        for (auto [x, y] : ps) {
            xs.add(x);
        }
        xs.build();
        while (sz < xs.size()) sz <<= 1;
        ys.resize(2 * sz);
        for (auto [x, y] : ps) {
            int i = xs.get(x) + sz;
            ys[i].add(y);
            while (i > 1) {
                i >>= 1;
                ys[i].add(y);
            }
        }
        for (int i = 0; i < 2 * sz; i++) {
            ys[i].build();
            data.emplace_back(data_structure(ys[i].size()));
        }
    }

    void set(int i, int j, S val) {
        i = xs.get(i);
        i += sz;
        data[i].set(ys[i].get(j), val);
        while (i > 1) {
            i >>= 1;
            S res = e();
            if (ys[2 * i].find(j)) {
                res = op(res, data[2 * i].get(ys[2 * i].get(j)));
            }
            if (ys[2 * i + 1].find(j)) {
                res = op(res, data[2 * i + 1].get(ys[2 * i + 1].get(j)));
            }
            data[i].set(ys[i].get(j), res);
        }
    }

    S get(int i, int j) const {
        i = xs.get(i) + sz;
        return data[i].get(ys[i].get(j));
    }

    S prod(int l, int d, int r, int u) const {
        l = xs.get(l) + sz;
        r = xs.get(r) + sz;
        S res = e();
        while (l < r) {
            if (l & 1) {
                res = op(res, data[l].prod(ys[l].get(d), ys[l].get(u)));
                l++;
            }
            if (r & 1) {
                r--;
                res = op(data[r].prod(ys[r].get(d), ys[r].get(u)), res);
            }
            l >>= 1;
            r >>= 1;
        }
        return res;
    }

  private:
    int sz = 1;
    std::vector<std::pair<int, int>> ps;
    compress<int> xs;
    std::vector<compress<int>> ys;
    std::vector<data_structure> data;
};

}  // namespace ebi
Back to top page