Tree line learning materials

Preface:

Had decided to go to completion of the data structure to learn something, the result has been goo until now. .

Segment tree is an advanced data structure.

It is a binary tree, that is, for a segment, we will be represented by a binary tree.

text:

Segment tree can do a single point of inquiry, a single point of modification, the query interval, the interval modification ......

General segment tree is

Let's give an example

Now I have such a string of numbers:

Put him in a tree line, it becomes the case:

Then each leaf node is the father of his son's values and this is a common tree line:

We put every node in the order marked with numbers:

We found that the son of each node and its serial number the number itself is a relationship ---- its own serial number is a , left his son's No. 2A , and the right number is the son of 2A + 1 .
So, we went down recursively built up from a tree line.

definition

int input[500005];//用来存放输入的数组。
struct node{
    int l,r,sum;//l和r分别表示当前节点表示的范围,sum是这个节点的值。
}tree[4*500005];//线段树的空间要开到原数组的4倍,否则会死的很惨。

Contribute

void build(int i,int l,int r){//递归建树,一般来说,调用的时候,i的位置填1,l和r分别填输入的数组的第一个序号和最后一个序号。
   tree[i].l=l;tree[i].r=r;
   if(l==r){//如果这个节点是叶子节点
       tree[i].sum=input[l];
       return ;
   }
   int mid=(l+r)>>1;
   build(i*2,l,mid);
   build(i*2+1,mid+1,r);//分别构造左子树和右子树
   tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;//然后由儿子推到父亲。
    return ;
}

Next we come to learn some basic operations

Interval modification

If this interval is fully included in the target zone inside, tell this section flag k

Code

inline void add(int i,int l,int r,int k){
    if(tree[i].l>=l && tree[i].r<=r){//如果这个区间被完全包括在目标区间里面,讲这个区间标记k
        tree[i].sum+=k;
        return ;
    }
    if(tree[i*2].r>=l)
        add(i*2,l,r,k);
    if(tree[i*2+1].l<=r)
        add(i*2+1,l,r,k);
}

A single point of inquiry

The so-called single point of inquiry is to ask you after the meal simple calculations of the current value of the operation * number is.

Just on this chart, for example: I want to know the value of the number 5.

This yields the following search

The scope of the search is to determine the node, if the node happens to be, directly output. If the node is included in this years, it continues to refine.

Code

void search(int i,int dis){
    if(tree[i].l==tree[i].r) {
         return tree[i].sum;
    }
    int mid=(tree[i].l+tree[i].r)/2;
    if(dis<=mid) return search(i*2,dis);
    else return search(i*2+1,dis);
}

-------------------------------------------------- -Dividing line----------------------------------------------- -------------------------------

Interval inquiry

And almost single point of inquiry, can be understood as (there are a range of) a single point of inquiry. Some node contains exactly this range, you can directly add the phrase.

Code

int search(int i,int l,int r){
    if(tree[i].l>=l&&tree[i].r<=r)
        return tree[i].sum;
    if(tree[i].r<l||tree[i].l>r) return 0;
    int s=0;
    if(tree[i*2].r>=1) s+=search(i*2,l,r);
    if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r);
    return s;
}

A single point of modification

Our achievements are built from the bottom up, single-point modification time is modified from the top down, as long as the target node contains a plus point are the same number on it.

Code

inline void add(int i,int dis,int k){
    if(tree[i].l==tree[i].r){
        tree[i].sum+=k;
        return;
    }
    if(dis<=tree[i*2].r&&dis>=tree[i*2].l) tree[i].sum+=k,add(i*2,dis,k);
    else if(dis<=tree[i*2+1].r&&dis>=tree[i*2+1].l) tree[i].sum+=k,add(i*2+1,dis,k);
}

NOTE: The above section and modify the query interval can not be shared, read on you will know the reason

Now we have to implement changes and the interval between queries. If the above two put together there will be a problem when you want to query interval is not fully included in the revised section, there will be problems, so we need to use lazy mark.

Principle: When the above situation occurs, the first downstream lazy marker, then determination.

The code (ie the code segment tree template question 1)

void pushdown(ll i){
    if(tree[i].lazy!=0){
        tree[i*2].lazy+=tree[i].lazy;
        tree[i*2+1].lazy+=tree[i].lazy;
        ll mid=(tree[i].l+tree[i].r)/2;
        tree[i*2].num+=tree[i].lazy*(mid-tree[i*2].l+1);
        tree[i*2+1].num+=tree[i].lazy*(tree[i*2+1].r-mid);
        tree[i].lazy=0;
    }
    return ;
}
void add(ll i,ll l,ll r,ll k){
    if(tree[i].r<=r&&tree[i].l>=l) {
        tree[i].num+=k*(tree[i].r-tree[i].l+1);
        tree[i].lazy+=k;
        return;
    }
    pushdown(i);
    if(tree[i*2].r>=l)
        add(i*2,l,r,k);
    if(tree[i*2+1].l<=r)
        add(i*2+1,l,r,k);
    tree[i].num=tree[i*2].num+tree[i*2+1].num;
    return;
} 

ll search(ll i,ll l,ll r)
{
    if(tree[i].l>=l && tree[i].r<=r)
    return tree[i].num;
    if(tree[i].r<l||tree[i].l>r) return 0;
    pushdown(i);
    ll s=0;
    if(tree[i*2].r>=l) s+=search(i*2,l,r);
    if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r);
    return s; 
}

Online segment template tree multiplication appeared in 2

At this time, the same did not like the addition, because of the different operators, the order of operations is not the same.

This would mark labeled lazy when passing under, we need to consider, is the first increase and then take the first or take together. We just need to do so lazy mark a process.

Lazy mark is divided into two, namely, the addition and multiplication plz mlz.

Similarly the code above, a plurality of function

(Segment tree template question 2) Code

 void pushdown(ll i){
    ll k1=tree[i].mlz,k2=tree[i].plz;
    tree[i<<1].sum=(tree[i<<1].sum*k1+k2*(tree[i<<1].r-tree[i<<1].l+1))%p;
    tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+k2*(tree[i<<1|1].r-tree[i<<1|1].l+1))%p;
    tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;
    tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;
    tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;
    tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;
    tree[i].plz=0;
    tree[i].mlz=1;
    return ;
}
inline void mul(ll i,ll l,ll r,ll k){
    if(tree[i].r<l || tree[i].l>r)  return ;
    if(tree[i].l>=l && tree[i].r<=r){
        tree[i].sum=(tree[i].sum*k)%p;
        tree[i].mlz=(tree[i].mlz*k)%p;
        tree[i].plz=(tree[i].plz*k)%p;
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)  mul(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)  mul(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
    return ;
}
void add(ll i,ll l,ll r,ll k){
    if(tree[i].r<l || tree[i].l>r)  return ;
    if(tree[i].l>=l && tree[i].r<=r){
        tree[i].sum+=((tree[i].r-tree[i].l+1)*k)%p;
        tree[i].plz=(tree[i].plz+k)%p;
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)  add(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)  add(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
    return ;
}
ll search(ll i,ll l,ll r){
    if(tree[i].r<l || tree[i].l>r)  return 0;
    if(tree[i].l>=l && tree[i].r<=r)
        return tree[i].sum;
    pushdown(i);
    ll sum=0;
    if(tree[i<<1].r>=l)  sum+=search(i<<1,l,r)%p;
    if(tree[i<<1|1].l<=r)  sum+=search(i<<1|1,l,r)%p;
    return sum%p;
}

Finally, the code template four questions were put about

[Template] Fenwick tree 1

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x) {
    x = 0;
    int f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + (ch ^ 48);
        ch = getchar();
    }
    x *= f;
    return;
}
template <typename T>
inline void write(T x)
{
    if(x < 0) {
        putchar('-');
        x = -x;
    }
    if(x > 9)
        write(x/10);
    putchar(x % 10 + '0');
    return;
}
int n,m,p;
int input[500005];
struct node{
    int l,r,sum;
}tree[4*500005];
inline void build(int i,int l,int r){
    tree[i].l=l,tree[i].r=r;
    if(l==r){
        tree[i].sum=input[l];
        return;
    }
    int mid=(l+r)>>1;
    build(i*2,l,mid);build(i*2+1,mid+1,r);
    tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
    return;
}
inline int search(int i,int l,int r){
    if(tree[i].l>=l&&tree[i].r<=r)
        return tree[i].sum;
    if(tree[i].r<l||tree[i].l>r) return 0;
    int s=0;
    if(tree[i*2].r>=1) s+=search(i*2,l,r);
    if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r);
    return s;
}
inline void add(int i,int dis,int k){
    if(tree[i].l==tree[i].r){
        tree[i].sum+=k;
        return;
    }
    if(dis<=tree[i*2].r) add(i*2,dis,k);
    else add(i*2+1,dis,k);
    tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}

int main(){
    int a,b,c,d;
    read(n),read(m);
    for(int i=1;i<=n;i++)
        read(input[i]);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        read(a),read(b),read(c);
        if(a==1){
            add(1,b,c);
        }
        else{
            write(search(1,b,c)),cout<<endl;
        }
    }
}

[Template] Fenwick tree 2

#include<bits/stdc++.h>
using namespace std;
template <typename T>
void read(T &x) {
    x = 0;
    int f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + (ch ^ 48);
        ch = getchar();
    }
    x *= f;
    return;
}
template <typename T>
void write(T x)
{
    if(x < 0) {
        putchar('-');
        x = -x;
    }
    if(x > 9)
        write(x/10);
    putchar(x % 10 + '0');
    return;
}

int n,m,a,b,c,ans,f;
struct Tree{
    int l,r,num;
}tree[500005*4]; 
int input[500005];
inline void build(int i,int l,int r){
    tree[i].l=l,tree[i].r=r;
    if(l==r){
        tree[i].num=input[l];
        return;
    }
    int mid=(l+r)/2;
    build(i*2,l,mid);build(i*2+1,mid+1,r);
    tree[i].num=tree[i*2].num+tree[i*2+1].num;
}

inline void add(int i,int l,int r,int k)
{
    if(tree[i].l>=l&&tree[i].r<=r){
        tree[i].num+=k;
        return;
    }
    if(tree[i*2].r>=l)
        add(i*2,l,r,k);
    if(tree[i*2+1].l<=r)
        add(i*2+1,l,r,k);
}
inline void search(int i,int dis){//此处的代码和上文讲的不太一样,都可以。
    ans+=tree[i].num;
    if(tree[i].l==tree[i].r) {
         return ;
    }
    int mid=(tree[i].l+tree[i].r)/2;
    if(dis<=mid) search(i*2,dis);
    if(dis>mid) search(i*2+1,dis);
}
int main(){
    read(n),read(m);
    build(1,1,n);
    for(int i=1;i<=n;i++)
        read(input[i]);
    for(int i=1;i<=m;i++)
    {
        read(f);
        if(f==1){
            read(a),read(b),read(c);
            add(1,a,b,c);
        }
        else{
            ans=0;
            read(a);
            search(1,a);
            cout<<ans+input[a]<<endl;
        }
        
    }
}

[Template] segment tree 1

#include<bits/stdc++.h>
#define ll long long
using namespace std;

template <typename T>
inline void read(T &x) {
    x = 0;
    ll f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + (ch ^ 48);
        ch = getchar();
    }
    x *= f;
    return;}
template <typename T>
inline void write(T x){
    if(x < 0) {
        putchar('-');
        x = -x;
    }
    if(x > 9)
        write(x/10);
    putchar(x % 10 + '0');
    return;
}

ll n,m,input[500005],a,b,c,d;
struct Tree{
    ll l,r,num,lazy;
}tree[500005*4];
inline void build(ll i,ll l,ll r){
    tree[i].l=l,tree[i].r=r;
    if(l==r){
        tree[i].num=input[l];
        return;
    }
    ll mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    tree[i].num=tree[i*2].num+tree[i*2+1].num;
}
inline void pushdown(ll i){
    if(tree[i].lazy!=0){
        tree[i*2].lazy+=tree[i].lazy;
        tree[i*2+1].lazy+=tree[i].lazy;
        ll mid=(tree[i].l+tree[i].r)/2;
        tree[i*2].num+=tree[i].lazy*(mid-tree[i*2].l+1);
        tree[i*2+1].num+=tree[i].lazy*(tree[i*2+1].r-mid);
        tree[i].lazy=0;
    }
    return ;
}
inline void add(ll i,ll l,ll r,ll k){
    if(tree[i].r<=r&&tree[i].l>=l) {
        tree[i].num+=k*(tree[i].r-tree[i].l+1);
        tree[i].lazy+=k;
        return;
    }
    pushdown(i);
    if(tree[i*2].r>=l)
        add(i*2,l,r,k);
    if(tree[i*2+1].l<=r)
        add(i*2+1,l,r,k);
    tree[i].num=tree[i*2].num+tree[i*2+1].num;
    return;
} 

inline ll search(ll i,ll l,ll r)
{
    if(tree[i].l>=l && tree[i].r<=r)
    return tree[i].num;
    if(tree[i].r<l||tree[i].l>r) return 0;
    pushdown(i);
    ll s=0;
    if(tree[i*2].r>=l) s+=search(i*2,l,r);
    if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r);
    return s; 
}
int main(){
    read(n),read(m);
    for(register ll i=1;i<=n;i++)   
        read(input[i]);
    build(1,1,n);
    for(register ll i=1;i<=m;i++){
        read(d);
        if(d==1) read(a),read(b),read(c),add(1,a,b,c);
        else read(a),read(b),write(search(1,a,b)),cout<<'\n';
    }
} 

[Template] segment tree 2

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,p;
ll input[100010];
struct node{
    ll l,r;
    ll sum,mlz,plz;
}tree[4*100010];
inline void build(ll i,ll l,ll r){
    tree[i].l=l;
    tree[i].r=r;
    tree[i].mlz=1;
    if(l==r){
        tree[i].sum=input[l]%p;
        return ;
    }
    ll mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
    return ;
}
inline void pushdown(ll i){
    ll k1=tree[i].mlz,k2=tree[i].plz;
    tree[i<<1].sum=(tree[i<<1].sum*k1+k2*(tree[i<<1].r-tree[i<<1].l+1))%p;
    tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+k2*(tree[i<<1|1].r-tree[i<<1|1].l+1))%p;
    tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;
    tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;
    tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;
    tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;
    tree[i].plz=0;
    tree[i].mlz=1;
    return ;
}
inline void mul(ll i,ll l,ll r,ll k){
    if(tree[i].r<l || tree[i].l>r)  return ;
    if(tree[i].l>=l && tree[i].r<=r){
        tree[i].sum=(tree[i].sum*k)%p;
        tree[i].mlz=(tree[i].mlz*k)%p;
        tree[i].plz=(tree[i].plz*k)%p;
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)  mul(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)  mul(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
    return ;
}
inline void add(ll i,ll l,ll r,ll k){
    if(tree[i].r<l || tree[i].l>r)  return ;
    if(tree[i].l>=l && tree[i].r<=r){
        tree[i].sum+=((tree[i].r-tree[i].l+1)*k)%p;
        tree[i].plz=(tree[i].plz+k)%p;
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)  add(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)  add(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
    return ;
}
inline ll search(ll i,ll l,ll r){
    if(tree[i].r<l || tree[i].l>r)  return 0;
    if(tree[i].l>=l && tree[i].r<=r)
        return tree[i].sum;
    pushdown(i);
    ll sum=0;
    if(tree[i<<1].r>=l)  sum+=search(i<<1,l,r)%p;
    if(tree[i<<1|1].l<=r)  sum+=search(i<<1|1,l,r)%p;
    return sum%p;
}
int main(){
    scanf("%lld%lld%lld",&n,&m,&p);
    for(int i=1;i<=n;i++)  scanf("%lld",&input[i]);
    build(1,1,n); 
    for(int i=1;i<=m;i++){
        ll f1,a,b,c;
        scanf("%lld",&f1);
        if(f1==1)
            scanf("%lld%lld%lld",&a,&b,&c),mul(1,a,b,c);
        if(f1==2)
            scanf("%lld%lld%lld",&a,&b,&c),add(1,a,b,c);
        if(f1==3)
            scanf("%lld%lld",&a,&b),printf("%lld\n",search(1,a,b));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/iloveori/p/12525886.html