20,190,616 weights segment tree

Segment tree Gugu Gu

I resolved to write the weight of a good segment tree to write it

What is the weight segment tree

Each segment tree maintenance point is the value of point, line weights and leaves point to maintain the number of times a number appeared, the parent node maintains that it represents the number of sections in the number of emerging and

Weight segment tree Basic Operation

In fact, the weight of the tree line and the basic operation is not much different tree line

Contribute

Note: Due to the number of times a leaf node represents a number appears, therefore, in the range of a few very large, we often need to put these rows of a sequence, ordered by re-assignment (because the weight value segment tree in the number itself is not important we just need to focus on the number of times it appears), which is also known as discrete

 

void build(int l,int r,int ro)
{
    tr[ro].l = l,tr[ro].r = r;
    if(l == r)tr[ro].w = 0;
    else 
    {
        int mid = (l + r) / 2;
        build(l,mid,2 * ro);
        build(mid + 1,r,2 * ro + 1);
        tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w;
    }
}

Add to

It is to find the leaf nodes represent this number, it weights ++

void add(int x,int ro)
{
    if(tr[ro].l == tr[ro].r && tr[ro].l == x)tr[ro].w ++;
    else 
    {
        int mid = (tr[ro].l + tr[ro].r) / 2;
        if(x <= mid)add(x,2 * ro);
        else if(x > mid)add(x,2 * ro + 1);
        tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w;
    }
}


Query Occurrences

Example: luogu p1903 reverse order

Queries and query operations segment tree of the same,

If the node represents the interval and the interval corresponding to the query and returns its weight

To query interval is within the range of the left child node to its left child node query

To query interval is within the range right child node to its right child query

Range across the range of about child node to node query, that query were to the left and right child nodes, and add and

int find(int l,int r,int ro)
{
    if(tr[ro].l == l && tr[ro].r == r)return tr[ro].w;
    else 
    {
        int mid = (tr[ro].l + tr[ro].r) / 2;
        if(r <= mid)return find(l,r,2 * ro);
        else if(l > mid)return find(l,r,2 * ro + 1);
        else return find(l,mid,2 * ro) + find(mid + 1,r,2 * ro + 1);
    }
}


Find k-th largest number

Example: luogu p3332 [ZJOI2013] K Tarsus query (this is a relationship problem I could find in Los ri)

Finding a large number of k, it is equivalent to looking for the first kk (kk = n- k + 1) small numbers

If kk <scope left child node, looking like a child node in the left

If kk> range left child node, indicating this number in the right child node where to find the right child node, however, be noted that the value of kk to minus range left child node, to represent us in the right child tree to find the first kk - tr [zuo] .w + 1 small numbers

If it can find a leaf node, the number of leaf nodes that represent shall ask

int numk(int l,int r,int ro,int k)
{
    if(l == r)return l;
    else 
    {
        int mid = (l + r) / 2;
        if(k <= tr[2 * ro].w)return numk(l,mid,2 * ro,k);
        else return numk(mid + 1,r,2 * ro + 1,k - tr[ro].w);
    }
}

 

40 affixed to a reverse code division

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct in
{
    int w;
    int k;
}a[500005];
struct node
{
    int l,r,w;
}tr[4000005];
void build(int l,int r,int ro)
{
    tr[ro].l = l,tr[ro].r = r;
    if(l == r)tr[ro].w = 0;
    else 
    {
        int mid = (l + r) / 2;
        build(l,mid,2 * ro);
        build(mid + 1,r,2 * ro + 1);
        tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w;
    }
}
int find(int l,int r,int ro)
{
    if(tr[ro].l == l && tr[ro].r == r)return tr[ro].w;
    else 
    {
        int mid = (tr[ro].l + tr[ro].r) / 2;
        if(r <= mid)return find(l,r,2 * ro);
        else if(l > mid)return find(l,r,2 * ro + 1);
        else return find(l,mid,2 * ro) + find(mid + 1,r,2 * ro + 1);
    }
}
void add(int x,int ro)
{
    if(tr[ro].l == tr[ro].r && tr[ro].l == x)tr[ro].w ++;
    else 
    {
        int mid = (tr[ro].l + tr[ro].r) / 2;
        if(x <= mid)add(x,2 * ro);
        else if(x > mid)add(x,2 * ro + 1);
        tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w;
    }
}
bool cmp(in x,in y)
{
    return x.w < y.w;
}
bool cmpp(in x,in y)
{
    return x.k < y.k;
}
int main()
{
    int n;
    int ans = 0;
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++)
    {
        scanf("%d",&a[i].w);
        a[i].k = i;
    }
    sort(a + 1,a + 1 + n,cmp);
    for(int i = 1;i <= n;i ++)
    {
        a[i].w = i;
    }
    sort(a + 1,a + 1 + n,cmpp);
    build(1,n,1);
    for(int i = 1;i <= n;i ++)
    {
        ans += find(a[i].w,n,1);
        add(a[i].w,1);
    }
    printf("%d",ans);
    return 0;
}


Welcome chiefs pointed the wrong ah

 

Guess you like

Origin www.cnblogs.com/djfuuxjz/p/11030217.html