ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线段树

2022-08-08 12:34:49  阅读:128  来源: 互联网

标签:return rr int 线段 tree add ll


线段树

模板

二倍空间(by Tourist)

Code
class segtree {
public:
    struct node {
        // don't forget to set default value (used for leaves)
        ... a = ...;

        void apply(int l, int r, ... v) {
            // make v become node(tag,data) in modify
            ...

            /*
            sum += (r - l + 1) * v;
            add += v;
            */
        }
        void init(... v) {
            // in build_tree init
            // sum=v;
        }
    };

    node unite(const node &a, const node &b) const {
        node res;
        // res.sum = a.sum + b.sum;
        ... return res;
    }
    // about x: left son is x+1 , right son is x+((mid-l+1)<<1) ;
    inline void push_down(int x, int l, int r) {
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        // push from x into (x + 1) and z
        ...
        /*
            if (tree[x].add != 0) {
              tree[x + 1].apply(l, y, tree[x].add);
              tree[z].apply(y + 1, r, tree[x].add);
              tree[x].add = 0;
            }
        */
    }

    int n;
    vector<node> tree;
    inline void push_up(int x, int z) { tree[x] = unite(tree[x + 1], tree[z]); }
    void build(int x, int l, int r) {
        if (l == r) {
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        build(x + 1, l, y);
        build(z, y + 1, r);
        push_up(x, z);
    }

    template <typename M>
    void build(int x, int l, int r, const vector<M> &v) {
        if (l == r) {
            tree[x].init(v[l]);
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        build(x + 1, l, y, v);
        build(z, y + 1, r, v);
        push_up(x, z);
    }

    node get(int x, int l, int r, int ll, int rr) {
        if (ll <= l && r <= rr) {
            return tree[x];
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        push_down(x, l, r);
        node res{};
        if (rr <= y)
            res = get(x + 1, l, y, ll, rr);
        else {
            if (ll > y)
                res = get(z, y + 1, r, ll, rr);
            else
                res = unite(get(x + 1, l, y, ll, rr), get(z, y + 1, r, ll, rr));
        }
        push_up(x, z);
        return res;
    }

    template <typename M>
    void modify(int x, int l, int r, int ll, int rr, const M &v) {
        if (ll <= l && r <= rr) {
            tree[x].apply(l, r, v);
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        push_down(x, l, r);
        if (ll <= y) modify(x + 1, l, y, ll, rr, v);
        if (rr > y) modify(z, y + 1, r, ll, rr, v);
        push_up(x, z);
    }

    segtree(int _n) : n(_n) {
        assert(n > 0);
        tree.resize(2 * n - 1);
        build(0, 0, n - 1);
    }

    template <typename M>
    segtree(const vector<M> &v) {
        n = v.size();
        assert(n > 0);
        tree.resize(2 * n - 1);
        build(0, 0, n - 1, v);
    }

    node get(int ll, int rr) {
        assert(0 <= ll && ll <= rr && rr <= n - 1);
        return get(0, 0, n - 1, ll, rr);
    }

    node get(int p) {
        assert(0 <= p && p <= n - 1);
        return get(0, 0, n - 1, p, p);
    }

    template <typename M>
    void modify(int ll, int rr, const M &v) {
        assert(0 <= ll && ll <= rr && rr <= n - 1);
        modify(0, 0, n - 1, ll, rr, v);
    }

};  // root's idx is 0 and the begin of vector is also 0;
    // don't forget idx is from 0 to n-1 (equal [--x,--y]) when ask;

四倍空间(不好用)

Code
int n;
struct tag{
    long long add;
    tag(long long ADD=0):add(ADD){}
    tag operator+=(const tag&other){
        add=add+other.add;
        return *this;
    }
    void clear(){
        add=0;
    }
    int empty(){
        return (!add);
    }
};
struct Data{
    long long sum,len;
    Data operator+ (const Data &other){
        Data ans;
        ans.sum=sum+other.sum;
        ans.len=len+other.len;
        return ans;
    }
    Data operator+= (const tag&other){
        sum=sum+len*other.add;
        return *this;
    }
};
struct Seg_tree{
    #define mid ((l +r) >> 1)
    #define ls (p<<1)
    #define rs (p<<1|1)
    tag t[N<<2];
    Data d[N<<2];
    void push_up(int p){d[p]=d[ls]+d[rs];}
    void updata (int p,tag k){t[p]+=k,d[p]+=k;}
    void push_down(int p) {if(!t[p].empty()){updata(ls,t[p]);updata(rs,t[p]);t[p].clear();}}
    void build(int p=1, int l=1, int r=n){
        t[p].clear();
        if (l == r)return (void)(d[p].sum=a[l],d[p].len=1);
        build(ls, l, mid), build(rs, mid + 1, r);
        push_up(p);
    }
    void change(int ll,int rr,tag k,int p=1,int l=1,int r=n){
        if(ll<=l&&r<=rr)return updata(p,k);
        push_down(p);
        if(ll<=mid)change(ll,rr,k,ls,l,mid);
        if(rr>mid)change(ll,rr,k,rs,mid+1,r);
        push_up(p);
    }
    Data ask(int ll, int rr,int p=1,int l=1,int r=n){
        if (ll <=l &&r <= rr)return d[p];
        push_down(p);bool fg1=(ll<=mid),fg2=(rr>mid);
        if(fg1&&fg2)return ask(ll,rr,ls,l,mid)+ask(ll,rr,rs,mid+1,r);
        if(fg1)return ask(ll,rr,ls,l,mid);
        return ask(ll,rr,rs,mid+1,r);
    }
}T;

示例

线段树2 P3373
区间乘加

Code
int a[N],n;
struct tag{
    int mul,add;
    tag(int a=1,int b=0):mul(a),add(b){}
    tag operator+=(const tag&cnm){
        mul=(mul*cnm.mul)%mod;
        add=(add*cnm.mul+cnm.add)%mod;
        return *this;
    }
    void clear(){
        add=0,mul=1;
    }
    int empty(){
        return (!add)&&(mul==1);
    }
};
struct Data{
    int sum,len;
    Data operator+ (const Data &cnm){
        Data ans;
        ans.sum=(sum+cnm.sum)%mod;
        ans.len=len+cnm.len;
        return ans;
    }
    Data operator+= (const tag&cnm){
        sum=(sum*cnm.mul+len*cnm.add)%mod;
        return *this;
    }
};
struct Seg_tree{
    #define mid ((l +r) >> 1)
    #define ls (p<<1)
    #define rs (p<<1|1)
    tag t[N<<2];
    Data d[N<<2];
    void push_up(int p){d[p]=d[ls]+d[rs];}
    void updata (int p,tag k){t[p]+=k,d[p]+=k;}
    void push_down(int p) {if(!t[p].empty()){updata(ls,t[p]);updata(rs,t[p]);t[p].clear();}}
    void build(int p, int l, int r){t[p].clear();if (l == r)return (void)(d[p]={a[l],1});build(ls, l, mid), build(rs, mid + 1, r);push_up(p);}
    void change(int p,int l,int r,int ll,int rr,tag k){if(ll<=l&&r<=rr)return updata(p,k);push_down(p);if(ll<=mid)change(ls,l,mid,ll,rr,k);if(rr>mid)change(rs,mid+1,r,ll,rr,k);push_up(p);}
    Data ask(int p,int l,int r,int ll, int rr){if (ll <=l &&r <= rr)return d[p];push_down(p);bool fg1=(ll<=mid),fg2=(rr>mid);if(fg1&&fg2)return ask(ls,l,mid,ll,rr)+ask(rs,mid+1,r,ll,rr);if(fg1)return ask(ls,l,mid,ll,rr);return ask(rs,mid+1,r,ll,rr);}
    void change(int l,int r,tag k){change(1,1,n,l,r,k);}
    Data ask(int l,int r){return ask(1,1,n,l,r);}
}T;

P4315 月下“毛景树”
区间染色, 区间加

Code
class segtree {
public:
    struct node {
        // don't forget to set default value (used for leaves)
        i64 maxx = inf;
        i64 add = 0;
        i64 ass = inf;
        void apply(int l, int r, i64 v) {
            // make v become node(tag,data) in modify
            add += v;
            maxx += v;
        }
        void init(i64 v) {
            // in build_tree init
            maxx = v;
            add = 0;
            ass = inf;
        }
    };

    node unite(const node &a, const node &b) const {
        node res;
        res.maxx = max(a.maxx, b.maxx);
        return res;
    }
    // about x: left son is x+1 , right son is x+((mid-l+1)<<1) ;
    inline void push_down(int x, int l, int r) {
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        // push from x into (x + 1) and z
        if (tree[x].ass >= 0) {
            tree[x + 1].maxx = tree[x + 1].ass = tree[x].ass;
            tree[z].maxx = tree[z].ass = tree[x].ass;
            tree[x + 1].add = tree[z].add = 0;
            tree[x].ass = inf;
        }
        if (tree[x].add != 0) {
            tree[x + 1].apply(l, y, tree[x].add);
            tree[z].apply(y + 1, r, tree[x].add);
            tree[x].add = 0;
        }
    }
    
    int n;
    vector<node> tree;
    inline void push_up(int x, int z) { tree[x].maxx = max(tree[x + 1].maxx, tree[z].maxx); }
    void build(int x, int l, int r) {
        if (l == r) {
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        build(x + 1, l, y);
        build(z, y + 1, r);
        push_up(x, z);
    }
    
    template <typename M>
    void build(int x, int l, int r, const vector<M> &v) {
        if (l == r) {
            tree[x].init(v[l]);
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        build(x + 1, l, y, v);
        build(z, y + 1, r, v);
        push_up(x, z);
    }
    
    node get(int x, int l, int r, int ll, int rr) {
        if (ll <= l && r <= rr) {
            return tree[x];
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        push_down(x, l, r);
        node res{};
        if (rr <= y)
            res = get(x + 1, l, y, ll, rr);
        else {
            if (ll > y)
                res = get(z, y + 1, r, ll, rr);
            else
                res = unite(get(x + 1, l, y, ll, rr), get(z, y + 1, r, ll, rr));
        }
        push_up(x, z);
        return res;
    }
    
    template <typename M>
    void modify(int x, int l, int r, int ll, int rr, const M &v) {
        if (ll <= l && r <= rr) {
            tree[x].apply(l, r, v);
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        push_down(x, l, r);
        if (ll <= y) modify(x + 1, l, y, ll, rr, v);
        if (rr > y) modify(z, y + 1, r, ll, rr, v);
        push_up(x, z);
    }
    
    template <typename M>
    void assign(int x, int l, int r, int ll, int rr, const M v) {
        if (ll <= l && r <= rr) {
            tree[x].maxx = tree[x].ass = v;
            tree[x].add = 0;
            return;
        }
        int y = (l + r) >> 1;
        int z = x + ((y - l + 1) << 1);
        push_down(x, l, r);
        if (ll <= y)
            assign(x + 1, l, y, ll, rr, v);
        if (rr > y)
            assign(z, y + 1, r, ll, rr, v);
        push_up(x, z);
    }
    
    segtree(int _n) : n(_n) {
        assert(n > 0);
        tree.resize(2 * n - 1);
        build(0, 0, n - 1);
    }
    
    template <typename M>
    segtree(const vector<M> &v) {
        n = v.size();
        assert(n > 0);
        tree.resize(2 * n - 1);
        build(0, 0, n - 1, v);
    }
    
    node get(int ll, int rr) {
        assert(0 <= ll && ll <= rr && rr <= n - 1);
        return get(0, 0, n - 1, ll, rr);
    }
    
    node get(int p) {
        assert(0 <= p && p <= n - 1);
        return get(0, 0, n - 1, p, p);
    }
    
    template <typename M>
    void modify(int ll, int rr, const M &v) {
        assert(0 <= ll && ll <= rr && rr <= n - 1);
        modify(0, 0, n - 1, ll, rr, v);
    }
    template <typename M>
    void assign(int ll, int rr, const M &v) {
        assert(0 <= ll && ll <= rr && rr <= n - 1);
        assign(0, 0, n - 1, ll, rr, v);
    }

};  // root's idx is 0 and the begin of vector is also 0;
    // don't forget idx is from 0 to n-1 (equal [--x,--y]) when ask;

标签:return,rr,int,线段,tree,add,ll
来源: https://www.cnblogs.com/Cattle-Horse/p/16561379.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有