首页 > 其他分享 >[模板] 线段树

[模板] 线段树

时间:2022-11-27 15:55:37浏览次数:35  
标签:rt node return src int 线段 build 模板

线段树

template<class T, class F>
class SegmentTree {
    const int n;
    vector<T> node;

    void update(int rt, int l, int r, int pos, F f) {
        if (r < pos || l > pos) return;
        if (l == r) {
            node[rt] = f(node[rt]);
            return;
        }
        int mid = l + r >> 1;
        update(rt << 1, l, mid, pos, f);
        update(rt << 1 | 1, mid + 1, r, pos, f);
        node[rt] = node[rt << 1] + node[rt << 1 | 1];
    }


    T query(int rt, int l, int r, int x, int y) {
        if (l > y || r < x) return T::e();
        if (x <= l && r <= y) return node[rt];
        int mid = l + r >> 1;
        return query(rt << 1, l, mid, x, y) + query(rt << 1 | 1, mid + 1, r, x, y);
    }

public:
    SegmentTree(int _n) :n(_n), node(_n << 2, T::e()) {}
    SegmentTree(int _n, vector<T> &src) :n(_n), node(_n << 2, T::e()) {
        function<void(int, int, int)> build = [&](int rt, int l, int r) {
            if (l == r) {
                node[rt] = src[l];
                return;
            }
            int mid = l + r >> 1;
            build(rt << 1, l, mid);
            build(rt << 1 | 1, mid + 1, r);
            node[rt] = node[rt << 1] + node[rt << 1 | 1];
        };
        build(1, 1, n);
    }

    void update(int pos, F f) {
        update(1, 1, n, pos, f);
    }

    T query(int x, int y) {
        return query(1, 1, n, x, y);
    }
};
///线段树,建树O(nlogn)、修改查询O(logn),单点修改、区间查询

struct T {
    int val;
    static T e() { return T{ 0 }; }
    friend T operator+(const T &a, const T &b) { return { a.val + b.val }; }
};
///节点元封装类,定义单位元"e"、合并"+"
struct F {
    int diff;
    T operator()(const T &x) { return T{ diff + x.val }; }
};
///修改元封装类,定义映射"()"

懒标记线段树

template<class T, class F>
class SegmentTreeLazy {
    const int n;
    vector<T> node;
    vector<F> lazy;

    void push_down(int rt) {///向下传递懒标记并更新值
        node[rt << 1] = lazy[rt](node[rt << 1]);
        lazy[rt << 1] = lazy[rt](lazy[rt << 1]);
        node[rt << 1 | 1] = lazy[rt](node[rt << 1 | 1]);
        lazy[rt << 1 | 1] = lazy[rt](lazy[rt << 1 | 1]);
        lazy[rt] = F::e();
    }

    void update(int rt, int l, int r, int x, int y, F f) {///区间修改
        if (l > y || r < x) return;
        if (x <= l && r <= y) {
            node[rt] = f(node[rt]);
            lazy[rt] = f(lazy[rt]);
            return;
        }
        push_down(rt);
        int mid = l + r >> 1;
        update(rt << 1, l, mid, x, y, f);
        update(rt << 1 | 1, mid + 1, r, x, y, f);
        node[rt] = node[rt << 1] + node[rt << 1 | 1];
    }

    T query(int rt, int l, int r, int x, int y) {///询问区间
        if (l > y || r < x) return T::e();
        if (x <= l && r <= y) return node[rt];
        push_down(rt);
        int mid = l + r >> 1;
        return query(rt << 1, l, mid, x, y) + query(rt << 1 | 1, mid + 1, r, x, y);
    }

public:
    SegmentTreeLazy(int _n) :n(_n), node(_n << 2, T::e()), lazy(_n << 2, F::e()) {}

    SegmentTreeLazy(int _n, vector<T> &src) :n(_n), node(_n << 2, T::e()), lazy(_n << 2, F::e()) {
        function<void(int, int, int)> build = [&](int rt, int l, int r) {
            if (l == r) {
                node[rt] = src[l];
                return;
            }
            int mid = l + r >> 1;
            build(rt << 1, l, mid);
            build(rt << 1 | 1, mid + 1, r);
            node[rt] = node[rt << 1] + node[rt << 1 | 1];
        };
        build(1, 1, n);
    }

    void update(int x, int y, F f) {
        update(1, 1, n, x, y, f);
    }

    T query(int x, int y) {
        return query(1, 1, n, x, y);
    }
};
///懒标记线段树,建树O(nlogn)、修改查询O(logn),区间修改、区间查询

int p;
struct T {
    ll val;
    int len;
    static T e() { return T{ 0,0 }; }
    friend T operator+(const T &a, const T &b) { return T{ (a.val + b.val) % p,a.len + b.len }; }
};
///节点元封装类,定义单位元"e"、合并"+"
struct F {
    ll sum;
    ll mul;
    static F e() { return F{ 0,1 }; }
    T operator()(T x) { return T{ (mul * x.val % p + sum * x.len % p) % p,x.len }; }
    F operator()(F g) { return F{ (mul * g.sum % p + sum) % p,mul * g.mul % p }; }
};
///修改元封装类,定义单位元"e"、映射"()"、复合"()"

标签:rt,node,return,src,int,线段,build,模板
From: https://www.cnblogs.com/BlankYang/p/16929834.html

相关文章