"Data structure" board + segment tree and calculate the maximum field

Notice the premise of learning segment tree

Tree line basis using generally used four single-point modified single-point query interval to modify section inquiry

And the code is easy to understand, although the amount of code that is very long but did not prevent us from learning algorithm

Algorithms content

basic concept

1, similar to the form of tree line BST(Binary search tree)In some of the details to distinguish BST

2, the basic idea of the tree line: Divide and Conquer

3, each node is stored in a structure of the embodiment, the structure comprises the following

  • A left end point of the current node included in section, the right end point.

  • This interval to be maintained and the interval (or other interval and here we focused on).

4, his father segment tree nodes are nodes in conjunction with his son, which is the root of the entire range of the number of columns

5, for the tree line:

  • A node in the tree \ (K \) , the presence \ (K \) child nodes are \ (k × 2 \) and \ (. 1 + 2 × K \) .

  • For this node \ (K \) , the range interval to its left son \ ([L, MID] \) , its right son \ ([mid + 1, r ] \)

Tree line of code and ideas

Structure

const int N = ???;
struct Node {
    int l, r, w;
} tree[N << 2];

Remember to open the tree four times the space

Basic Operation of the segment tree has five: achievements, single query, modify a single point, the query interval, interval modification

Contribute

Ideas:

  • To each node point given interval left and right points
  • For each leaf node, we give them a known individual values
  • Using the properties of the segment tree, combined upward
void build(int k, int l, int r) {
    tree[k].l = l; tree[k].r = r;
    if(l == r) {
        scanf("%d", &tree[k].w);
        return ;
    }
    
    int mid = (l + r) >> 1;
    build(k * 2, l, mid);
    build(k * 2 + 1, mid + 1, r);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

Modifying single point (we assume here need to modify the point number is X, the need to add a value of T)

Ideas:

  • If the interval to find a point indicated by the point we are looking for include sections of the left and right sections so this point go aboard
  • We want to modify certain point in the leaf node, we find this part of the need to consume \ (O (logn) \)
  • Modification can lead to a point above the current section contains the point to be changed, so this step is to modify \ (O (logn) \)
//Now X and T has been entered;
void change_point(int k) {
    if(tree[k].l == tree[k].r) {
        tree[k].w += t;
        return ;
    }
    
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(mid >= x) change_point(k * 2);
    else change_point(k * 2 + 1);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

A single point of inquiry (set to be queried point here is x)

Ideas:

  • And similar single-point modification if looking for a point indicated by the intervals containing the point we are looking for the left and right interval interval then go aboard this point
//Now x has been entered;
int ans;
void ask_point(int k) {
    if(tree[k].l == tree[k].r) {
        ans = tree[k].w;
        return ;
    }
    
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(mid >= x) ask_point(k * 2);
    else ask_point(k * 2 + 1);
}

Query Interval (range set for the query [l, r])

Ideas:

  • And the idea of ​​a single point of inquiry is similar, but here replaced interval
//Now l and r has been entered
int ans;
void ask_interval(int k, int l, int r) {
    if(tree[k].l >= l && tree[k].r <= r) {
        ans += tree[k].w;
        return ;
    }
    
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(mid >= l) ask_interval(k * 2, l, r);
    if(mid < r) ask_interval(k * 2 + 1, l, r);
}

Interval modified (※)

Ideas:

  • Simply find and modify certain time out, we are here to introduce a new operation called Lazy (Lazy operation)
    • Lazy operation as you play MC server did not load blocks will not have any behavior , but in fact there Box and animals on this block, when you loaded this block, only some of the acts above normal of such furnaces burn things or seedlings grow.
    • Lazy operation actually is a kind of difference of ideology, some information is stored to some point, if this point is traversed, then information about the current point will be inherited by child nodes, if any other information on which child nodes, then this information It will not disappear
//Now l,r,x has been entered
struct Node {
    int l, r, w;
    int f;
} tree[N >> 2];

void Lazydown(int k) {
    tree[k * 2].f += tree[k].f;
    tree[k * 2].w += (tree[k * 2].r - tree[k * 2].l + 1) * tree[k].f;
    tree[k * 2 + 1].f += tree[k].f;
    tree[k * 2 + 1].w += (tree[k * 2 + 1].r - tree[k * 2 + 1].l + 1) * tree[k].f;
    tree[k].f = 0;
}

void change_interval(int k) {
    if(tree[k].l >= l && tree[k].r <= r) {
        tree[k].w += (tree[k].r - tree[k].l + 1) * x;
        tree[k].f += x;
        return ;
    }
    
    if(tree[k].f) Lazydown(k);
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(mid >= l) change_interval(k * 2);
    if(mid < r) change_interval(k * 2 + 1);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

There are several issues that need attention

  • Lazy labeled structure needs to be changed, a need to add the current node stored information
  • Here we find modifications become tree[k].w += (tree[k].r - tree[k].l + 1) * x;, where you can verify draw
  • Lazydown represent means that we have to traverse a number \ (k \) is the point, after it has traversed, certainly passes the information
  • Lazydown modification and operation principle of the modified interval is the same, if not understood, can get to the bottom drawing
  • Because we have passed and traversed, the information of the current point will be cleared(Otherwise, the pullback would (say game

Joined Lazydown later, we discovered that if traversed point operations should be carried out lazy, then all we need to modify the code

Full code is as follows

//#define fre yes 信仰

#include <cstdio>

const int N = 200005;
struct Node {
    int l, r, w;
    int f;
} tree[N >> 2];

void build(int k, int l, int r) {
    tree[k].l = l; tree[k].r = r;
    if(l == r) {
        scanf("%d", &tree[k].w);
        return ;
    }
    
    int mid = (l + r) >> 1;
    build(k * 2, l, mid);
    build(k * 2 + 1, mid + 1, r);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w
}

void Lazydown(int k) {
    tree[k * 2].f += tree[k].f;
    tree[k * 2].w += (tree[k * 2].r - tree[k * 2].l + 1) * tree[k].f;
    tree[k * 2 + 1].f += tree[k].f;
    tree[k * 2 + 1].w += (tree[k * 2 + 1].r - tree[k * 2 + 1].l + 1) * tree[k].f;
    tree[k].f = 0;
}

void change_point(int k, int x) {
    if(tree[k].l == tree[k].r) {
        tree[k].w += x;
        return ;
    }
    
    if(tree[k].f) Lazydown(k); 
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(mid >= l) change_point(k * 2);
    else change_point(k * 2 + 1);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

int ans_p;
void ask_point(int k) {
    if(tree[k].l == tree[k].r) {
        ans_p = tree[k].w;
        return ;
    }
    
    if(tree[k].f) Lazydown(k);
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(mid >= l) ask_point(k * 2);
    else ask_point(k * 2 + 1);
}

int ans_i;
void ask_interval(int k, int l, int r) {
    if(tree[k].l >= l && tree[k].r <= r) {
        ans_i += tree[k].w;
        return ;
    }
    
    if(tree[k].f) Lazydown(k);
    int mid = (tree[k].r - tree[k].l) >> 1;
    if(mid >= l) ask_interval(k * 2, l, r);
    if(mid < r) ask_interval(k * 2 + 1, l, r);
}

void change_interval(int k, int l, int r) {
    if(tree[k].l >= l && tree[k].r <= r) {
       tree[k].w += (tree[k].r - tree[k].l + 1) * x;
       tree[k].f += x;
       return ;
    }
    
    if(tree[k].f) Lazydown(k);
    int mid = (tree[k].r - tree[k].l) >> 1;
    if(mid >= l) change_interval(k * 2, l, r);
    if(mid < r) chnage_interval(k * 2 + 1, l, r);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

int main() {
    ...
}

Guess you like

Origin www.cnblogs.com/Nicoppa/p/11411199.html