Weight segment tree Detailed knowledge Basics

Weight segment tree

Learn weights tree line, we must first understand what the tree line Yes. If you can not first learn about.

What is

Weight tree line, as the name suggests is a segment tree.
But it is different from ordinary tree segment:
segment tree, each node maintains the maximum value for the sum or some other interval.
Weights segment tree, the equivalent of a bucket, for each node represents a section number of occurrences .

Why use it

We can use it to maintain the number of times for a range of emerging from its definition, it can quickly calculate the number of occurrences for a number of intervals.
In addition, it also has an important function is that it can quickly find the first $ k $ of $ k $ large or small value, the following will be explained in detail.
In fact, it is a bucket, the bucket can do it can be used faster to complete.

Basic Operations

Add to

Normal segment tree and the like, to $ f [v] + 1 $ recursive to leaf nodes.
The following code number to be added is $ x $, $ x $ is the number that appears $ + 1 $.

    void add(int l,int r,int v,int x)
    {
        if(l==r) f[v]++;
        else
        {
            int mid=(l+r)/2;
            if(x<=mid) add(l,mid,v*2,x); else add(mid+1,r,v*2+1,x);
            f[v]=f[v*2]+f[v*2+1];
        {
    }

A number of queries appear

When operations such as adding, to the leaf node recursively $ f [v] $ value is also desired number of times.
The following code to query the number is $ x $.

    int find(int l,int r,int v,int x)
    {
        if(l==r) return f[v];
        else
        {
            int mid=(l+r)/2;
            if(x<=mid) return find(l,mid,v*2,x); else return find(mid+1,r,v*2+1,x);
        }
    }

The number of queries for a range of emerging

The same query with the tree line, and constantly recursive half.
The following code to query interval is $ [x, y] $.

    int find(int l,int r,int v,int x,int y)
    {
        if(l==x&&r==y) return f[v];
        else
        {
            int mid=(l+r)/2;
            if(y<=mid) return find(l,mid,v*2,x,y);
            else if(x>mid) return find(mid+1,r,v*2+1,x,y);
            else return find(l,mid,v*2,x,mid)+find(mid+1,r,v*2+1,mid+1,y);
        }
    }

Queries k-th largest value of all numbers

This is the core of the segment tree weights, idea is as follows:
when the each node, if the sum is greater than or equal right subtree $ k $, $ k $ first described a large value appears in the right subtree, recursively into the right subtree ; otherwise the instructions at this time of the first $ k $ large value in the right subtree, recursively into the left subtree Note: at this point you want $ k $ value minus the sum of the right subtree.
Why should subtract?
If we are looking for are $ 7 $ a large value, right subtree sum of $ 4 $, $ 7-4 = 3 $, described are $ 3 $ a large value in the left subtree at the $ 7 $ a large value of the node.
When finally been recursion to only a number, that number is the answer.

    int kth(int l,int r,int v,int k)
    {
        if(l==r) return l;
        else
        {
            int mid=(l+r)/2,s1=f[v*2],s2=f[v*2+1];
            if(k<=s2) return kth(mid+1,r,v*2+1,k); else return kth(l,mid,v*2,k-s2);
        }
    }

to sum up

Basics weights tree line there is to it, I believe you have learned.
I hope you can be flexible, higher level in the future OI career.
If you want to learn advanced knowledge, you can look at [Chairman] tree may persist segment tree

Guess you like

Origin www.cnblogs.com/LZA119/p/11286409.html