线段树封装

Posted zhangtianli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树封装相关的知识,希望对你有一定的参考价值。

/*
*
* Name: Segment Tree
* Copyright (C) 2017-2019 zhangtianli
*
*/

/*
*
* basic operation
* 
* - in main
*   - tree "name"
*   - init()  *important
*   - build_single/_long()
*   - operation by changing val in struct "tree"
*   - used functions below
*   ** don't change the basic items
*
* functions:
*
*   1. void init(void)  make int Tree[] & add[]
*
*   2. void build_single(long long l, long long r, long long k)  bulid segnent tree by single update & query
*      l , r : build tree from point "l" to point "r"
*      k : start from which point number **should be 1 in defult
*
*   3. void bulid_long(long long l, long long r, long long k)  bulid segnent tree by long update & query
*      l , r : build tree from point "l" to point "r"
*      k : start from which point number **should be 1 in defult
*
*   4. void single_update(long long l, long long r, long long k, long long place, long long val) modify single element
*      l , r : search from point "l" to point "r" **should be 1 & n (element number) in defult
*      k : start point  **should be 1 in defult
*      val : modify key (could be change into others)
*
*   5. void long_update(long long l, long long r, long long k, long long a, long long b, long long val)  modify elements in a section
*      l , r : search from point "l" to point "r" **should be 1 & n (element number) in defult
*      k : start point  **should be 1 in defult
*      a , b : section's left point & right point
*      val : modify key (could be change into others)
*
*   6. inline long long long_query_single(long long l, long long r, long long k, long long a, long long b) querying a section
*      use with "build_single" & "single_update"
*      l , r : search from point "l" to point "r" **should be 1 & n (element number) in defult
*      k : start point  **should be 1 in defult
*      a , b : section's left point & right point
*      return : could be changed by user functions (basicly add and sum)
*
*   7. inline long long long_query_long(long long l, long long r, long long k, long long a, long long b) querying a section
*      use with "long_build" & "long_update"
*      l , r : search from point "l" to point "r" **should be 1 & n (element number) in defult
*      k : start point  **should be 1 in defult
*      a , b : section's left point & right point
*      return : could be changed by user functions (basicly add and sum)
*
* user functions:
*   changeable function **do not change 
*   
*   1. seted_single : use INF for normal
*   2. max_len : max_len of tree **it will be times 4 automatically
*   3. void make_tree_basic_single(long long x) last layer's operation in tree. used in "build_single"
*   4. void make_tree_basic_long(long long x) last layer's operation in tree. used in "build_long"
*   5. long long make_tree_single(long long l, long long r) normal point tree make. used in "build_single"
*   6. long long make_tree_long(long long l, long long r) normal point tree make. used in "build_long"
*   7. void update_single(long long pos, long long val) change single element used in "single_update" normally is Tree[pos] += val
*      pos : place that change val
*      val : val the change
*   8. void update_long(long long pos, long long val) change single element used in "long_update" normally is add[pos] += val;
*      pos : place that change val
*      val : val the change
*   9. inline long long comp_single(long long v1, long long v2) compare v1 & v2 used in "long_query_single"
*      sum : return v1 + v2
*      min : return std::min(v1, v2);
*      max : return std::max(v1, v2);
*   10. inline long long comp_long(long long v1, long long v2)  compare v1 & v2 used in "long_query_long"
*      sum : return v1 + v2
*      min : return std::min(v1, v2);
*      max : return std::max(v1, v2);
*
*/

struct tree 
// basic items--------------------------------------------------

    #include<string.h>
    #include<algorithm>
    long long *Tree; // basic val
    long long *add; // basic val

// basic items--------------------------------------------------

// user functions----------------------------------------------------------

    long long seted_single = /* val */;
    long long max_len = /* val */; /* val (times 4) */

    void make_tree_basic_single(long long x) 
        /* val */
    

    void make_tree_basic_long(long long x) 
        /* val */
    

    inline 
    long long make_tree_single(long long l, long long r) 
        /* val */
    

    inline 
    long long make_tree_long(long long l, long long r) 
        /* val */
    

    void update_single(long long pos, long long val) 
        /* val */
    

    void update_long(long long pos, long long val) 
        /* val */
    

    inline 
    long long comp_single(long long v1, long long v2) 
        /* val */
    

    inline 
    long long comp_long(long long v1, long long v2) 
        /* val */
    

// user functions------------------------------------------------------------

    void init() 
        Tree = new long long[max_len * 4];
        memset(Tree, 0, max_len * 4 * sizeof(long long));
        add = new long long[max_len * 4];
        memset(add, 0, max_len * 4 * sizeof(long long));
    

    void build_single(long long l, long long r, long long k) 
        if (l == r) 
            make_tree_basic_single(k);
            return;
        

        long long mid = (l + r) >> 1;
        long long ls = k << 1, rs = k << 1|1;
        build_single(l, mid, ls);
        build_single(mid + 1, r, rs);
        Tree[k] = make_tree_single(ls, rs);
    

    void build_long(long long l, long long r, long long k) 
        if (l == r) 
            make_tree_basic_long(k);
            return;
        

        long long mid = (l + r) >> 1;
        long long ls = k << 1, rs = k << 1|1;
        build_long(l, mid, ls);
        build_long(mid + 1, r, rs);
        Tree[k] = make_tree_long(ls, rs);
    

    void single_update(long long l, long long r, long long k, long long place, long long val) 
        if (l == r) 
            update_single(k, val);
            return;
        

        long long mid = (l + r) >> 1;
        long long ls = k << 1, rs = k << 1|1;
        if (place <= mid) single_update(l, mid, ls, place, val);
        else single_update(mid + 1, r, rs, place, val);
        Tree[k] = make_tree_single(ls, rs);
    

    void long_update(long long l, long long r, long long k, long long a, long long b, long long val) 
        if(l >= a && r <= b) 
            update_long(k, val);
            return;
        

        Tree[k] += (min(r, b) - max(l, a) + 1) * val;
        long long mid = (l + r) >> 1;
        long long ls = k << 1, rs = k << 1|1;
        if (a <= mid) long_update(l, mid, ls, a, b, val);
        if (b > mid) long_update(mid + 1, r, rs, a, b, val);
    

    inline 
    long long long_query_single(long long l, long long r, long long k, long long a, long long b) 
        if (a <= l && b >= r) return Tree[k];
        long long mid = (l + r) >> 1;
        long long ls = k << 1, rs = k << 1|1;
        long long tmp1 = seted_single, tmp2 = seted_single;
        if (a <= mid) tmp1 = long_query_single(l, mid, ls, a, b);
        if (b > mid) tmp2 = long_query_single(mid + 1, r, rs, a, b);
        return comp_single(tmp1, tmp2);
    

    inline 
    long long long_query_long(long long l, long long r, long long k, long long a, long long b) 
        if(l >= a && r <= b) return Tree[k] + (r - l + 1) * add[k];
        long long mid = (l + r) >> 1;
        long long ls = k << 1, rs = k << 1|1;
        long long tmp = (min(r, b) - max(l, a) + 1) * add[k];
        if (a <= mid) tmp += long_query_long(l, mid, ls, a, b);
        if (b > mid) tmp += long_query_long(mid + 1, r, rs, a, b);
        return tmp;
    
;

以上是关于线段树封装的主要内容,如果未能解决你的问题,请参考以下文章

One Occurrence 线段树离线维护最小值

错误记录加强版

权值线段树套序列线段树

一般线段树与权值线段树

详解权值线段树

权值线段树&&线段树合并