线段树封装

/*
*
* 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
    #include
    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;
    }
};

你可能感兴趣的:(线段树封装)