Felix's Library

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

View the Project on GitHub fffelix-huang/CP-stuff

:heavy_check_mark: library/data-structure/lazy-segtree.hpp

Depends on

Verified with

Code

#pragma once
#include <vector>
#include <algorithm>
#include <functional>
#include <cassert>
#include "segtree.hpp"

namespace felix {

template<class S,
         S (*e)(),
         S (*op)(S, S),
         class F,
         F (*id)(),
         S (*mapping)(F, S),
         F (*composition)(F, F)>
struct lazy_segtree : public segtree<S, e, op> {
	using base = segtree<S, e, op>;

public:
	lazy_segtree() {}
	explicit lazy_segtree(int _n) : lazy_segtree(std::vector<S>(_n, e())) {}
	explicit lazy_segtree(const std::vector<S>& v) : base(v), lz(size, id()) {}

	void set(int p, S x) {
		push_down(p);
		base::set(p, x);
	}

	S get(int p) {
		push_down(p);
		return base::get(p);
	}

	S operator[](int p) { return get(p); }

	S prod(int l, int r) {
		if(l == r) {
			return e();
		}
		push_down(l, r);
		return base::prod(l, r);
	}

	void apply(int p, F f) {
		assert(0 <= p && p < n);
		push_down(p);
		base::set(p, mapping(f, d[p]));
	}

	void apply(int l, int r, F f) {
		assert(0 <= l && l <= r && r <= n);
		if(l == r) {
			return;
		}
		push_down(l, r);
		l += size, r += size;
		{
			int l2 = l, r2 = r;
			while(l < r) {
				if(l & 1) {
					all_apply(l++, f);
				}
				if(r & 1) {
					all_apply(--r, f);
				}
				l >>= 1, r >>= 1;
			}
			l = l2, r = r2;
		}
		for(int i = 1; i <= log; i++) {
			if(((l >> i) << i) != l) {
				update(l >> i);
			}
			if(((r >> i) << i) != r) {
				update((r - 1) >> i);
			}
		}
	}

	template<bool (*g)(S)> int max_right(int l) {
		return max_right(l, [](S x) { return g(x); });
	}

	template<class G> int max_right(int l, G g) {
		assert(0 <= l && l <= n);
		assert(g(e()));
		if(l == n) {
			return n;
		}
		push_down(l);
		return base::max_right(l, g);
	}

	template<bool (*g)(S)> int min_left(int r) {
		return min_left(r, [](S x) { return g(x); });
	}

	template<class G> int min_left(int r, G g) {
		assert(0 <= r && r <= n);
		assert(g(e()));
		if(r == 0) {
			return 0;
		}
		push_down(r - 1);
		return base::min_left(r, g);
	}

protected:
	using base::n, base::log, base::size, base::d;
	using base::update;

	std::vector<F> lz;

	virtual void all_apply(int k, F f) {
		d[k] = mapping(f, d[k]);
		if(k < size) {
			lz[k] = composition(f, lz[k]);
		}
	}

	void push(int k) override {
		all_apply(2 * k, lz[k]);
		all_apply(2 * k + 1, lz[k]);
		lz[k] = id();
	}

	void push_down(int p) {
		p += size;
		for(int i = log; i >= 1; i--) {
			push(p >> i);
		}
	}

	void push_down(int l, int r) {
		l += size, r += size;
		for(int i = log; i >= 1; i--) {
			if(((l >> i) << i) != l) {
				push(l >> i);
			}
			if(((r >> i) << i) != r) {
				push((r - 1) >> i);
			}
		}
	}
};

} // namespace felix
#line 2 "library/data-structure/lazy-segtree.hpp"
#include <vector>
#include <algorithm>
#include <functional>
#include <cassert>
#line 6 "library/data-structure/segtree.hpp"

namespace felix {

template<class S, S (*e)(), S (*op)(S, S)>
struct segtree {
public:
    segtree() {}
    explicit segtree(int _n) : segtree(std::vector<S>(_n, e())) {}
    explicit segtree(const std::vector<S>& a): n(a.size()) {
        log = std::__lg(2 * n - 1);
        size = 1 << log;
        d.resize(size * 2, e());
        for(int i = 0; i < n; ++i) {
            d[size + i] = a[i];
        }
        for(int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }
    
    void set(int p, S val) {
        assert(0 <= p && p < n);
        p += size;
        d[p] = val;
        for(int i = 1; i <= log; ++i) {
            update(p >> i);
        }
    }

    S get(int p) const {
        assert(0 <= p && p < n);
        return d[p + size];
    }

    S operator[](int p) const { return get(p); }
    
    S prod(int l, int r) const {
        assert(0 <= l && l <= r && r <= n);
        S sml = e(), smr = e();
        for(l += size, r += size; l < r; l >>= 1, r >>= 1) {
            if(l & 1) {
                sml = op(sml, d[l++]);
            }
            if(r & 1) {
                smr = op(d[--r], smr);
            }
        }
        return op(sml, smr);
    }

    S all_prod() const { return d[1]; }

    template<bool (*f)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return f(x); });
    }

    template<class F> int max_right(int l, F f) {
        assert(0 <= l && l <= n);
        assert(f(e()));
        if(l == n) {
            return n;
        }
        l += size;
        S sm = e();
        do {
            while(~l & 1) {
                l >>= 1;
            }
            if(!f(op(sm, d[l]))) {
                while(l < size) {
                    push(l);
                    l <<= 1;
                    if(f(op(sm, d[l]))) {
                        sm = op(sm, d[l++]);
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l++]);
        } while((l & -l) != l);
        return n;
    }

    template<bool (*f)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return f(x); });
    }

    template<class F> int min_left(int r, F f) {
        assert(0 <= r && r <= n);
        assert(f(e()));
        if(r == 0) {
            return 0;
        }
        r += size;
        S sm = e();
        do {
            r--;
            while(r > 1 && (r & 1)) {
                r >>= 1;
            }
            if(!f(op(d[r], sm))) {
                while(r < size) {
                    push(r);
                    r = 2 * r + 1;
                    if(f(op(d[r], sm))) {
                        sm = op(d[r--], sm);
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while((r & -r) != r);
        return 0;
    }
    
protected:
    int n, size, log;
    std::vector<S> d;

    void update(int v) {
        d[v] = op(d[2 * v], d[2 * v + 1]);
    }

    virtual void push(int p) {}
};

} // namespace felix
#line 7 "library/data-structure/lazy-segtree.hpp"

namespace felix {

template<class S,
         S (*e)(),
         S (*op)(S, S),
         class F,
         F (*id)(),
         S (*mapping)(F, S),
         F (*composition)(F, F)>
struct lazy_segtree : public segtree<S, e, op> {
	using base = segtree<S, e, op>;

public:
	lazy_segtree() {}
	explicit lazy_segtree(int _n) : lazy_segtree(std::vector<S>(_n, e())) {}
	explicit lazy_segtree(const std::vector<S>& v) : base(v), lz(size, id()) {}

	void set(int p, S x) {
		push_down(p);
		base::set(p, x);
	}

	S get(int p) {
		push_down(p);
		return base::get(p);
	}

	S operator[](int p) { return get(p); }

	S prod(int l, int r) {
		if(l == r) {
			return e();
		}
		push_down(l, r);
		return base::prod(l, r);
	}

	void apply(int p, F f) {
		assert(0 <= p && p < n);
		push_down(p);
		base::set(p, mapping(f, d[p]));
	}

	void apply(int l, int r, F f) {
		assert(0 <= l && l <= r && r <= n);
		if(l == r) {
			return;
		}
		push_down(l, r);
		l += size, r += size;
		{
			int l2 = l, r2 = r;
			while(l < r) {
				if(l & 1) {
					all_apply(l++, f);
				}
				if(r & 1) {
					all_apply(--r, f);
				}
				l >>= 1, r >>= 1;
			}
			l = l2, r = r2;
		}
		for(int i = 1; i <= log; i++) {
			if(((l >> i) << i) != l) {
				update(l >> i);
			}
			if(((r >> i) << i) != r) {
				update((r - 1) >> i);
			}
		}
	}

	template<bool (*g)(S)> int max_right(int l) {
		return max_right(l, [](S x) { return g(x); });
	}

	template<class G> int max_right(int l, G g) {
		assert(0 <= l && l <= n);
		assert(g(e()));
		if(l == n) {
			return n;
		}
		push_down(l);
		return base::max_right(l, g);
	}

	template<bool (*g)(S)> int min_left(int r) {
		return min_left(r, [](S x) { return g(x); });
	}

	template<class G> int min_left(int r, G g) {
		assert(0 <= r && r <= n);
		assert(g(e()));
		if(r == 0) {
			return 0;
		}
		push_down(r - 1);
		return base::min_left(r, g);
	}

protected:
	using base::n, base::log, base::size, base::d;
	using base::update;

	std::vector<F> lz;

	virtual void all_apply(int k, F f) {
		d[k] = mapping(f, d[k]);
		if(k < size) {
			lz[k] = composition(f, lz[k]);
		}
	}

	void push(int k) override {
		all_apply(2 * k, lz[k]);
		all_apply(2 * k + 1, lz[k]);
		lz[k] = id();
	}

	void push_down(int p) {
		p += size;
		for(int i = log; i >= 1; i--) {
			push(p >> i);
		}
	}

	void push_down(int l, int r) {
		l += size, r += size;
		for(int i = log; i >= 1; i--) {
			if(((l >> i) << i) != l) {
				push(l >> i);
			}
			if(((r >> i) << i) != r) {
				push((r - 1) >> i);
			}
		}
	}
};

} // namespace felix
Back to top page