Line tree statistics

Summary of various line segment trees (all take the maximum as an example)

Line segment tree, used to query some specific values ​​of the interval (such as: maximum, minimum, average), support new creation, modification and query operations, the space should be opened 4 times, pay attention to the initialization when creating

1. New

void build(int l,int r,int x)
{
    
    
    tree[x]={
    
    l,r,0};//在这里不初始化也行,因为已经默认为0了
    if(l==r)
		return;
    int mid=l+r>>1;
    build(l,mid,x<<1);
    build(mid+1,r,x<<1|1);
}

2. Modify

void modify(int x,int u,int v)
{
    
    
    if(tree[x].l==u&&tree[x].r==u)//是那个点
    {
    
    
		tree[x].v=v;
		return;
    }
    int mid=tree[x].l+tree[x].r>>1;
    if(u<=mid)
        modify(x<<1,u,v);//那个点在左边
    else
        modify(x<<1|1,u,v);//反之
    tree[x].v=max(tree[x<<1].v,tree[x<<1|1].v);//上传
}

3. Query

int query(int x,int l,int r)
{
    
    
    if(tree[x].l>=l&&tree[x].r<=r)//在区间内
		return tree[x].v;
    int mid=tree[x].l+tree[x].r>>1,sum=0;
    if(l<=mid)
		sum=query(x<<1,l,r);
    if(r>mid)
		sum=max(sum,query(x<<1|1,l,r));//统计左右答案
    return sum;
}

Line segment tree deformation

1. Interval modification

In fact, if the modified interval is already included in the current interval, modify the entire interval and mark the following. If it is recursed, modify it

void pushdown(int x)
{
    
    
    tree[x<<1].add+=tree[x].add;
    tree[x<<1|1].add+=tree[x].add;//下传
    tree[x<<1].sum+=(tree[x<<1].r-tree[x<<1|1].l+1)*tree[x].add;
    tree[x<<1|1].sum+=(tree[x<<1|1].r-tree[x<<1|1|1].l+1)*tree[x].add;//更新值
}
void modify(int x,int l,int r,int v)
{
    
    
    if(tree[x].l>=l&&tree[x].r<=r)
    {
    
    
		tree[x].v+=(tr[x].r-tr[x].l+1)*v;
		tree[x].add+=v;//标记
		return;
    }
    pushdown(x);//下传
    int mid=tr[x].l+tr[x].r>>1;
    if(l<=mid)
        modify(x<<1,l,r,v);
    if(r>mid)
        modify(x<<1|1,l,r,v);
    tree[x].v=max(tree[x<<1].v,tree[x<<1|1].v);
}
int query(int x,int l,int r)
{
    
    
    if(tree[x].l>=l&&tree[x].r<=r)
		return tree[x].v;
    pushdown(x);//下传
    int mid=tree[x].l+tree[x].r>>1,sum=0;
    if(l<=mid)
		sum=query(x<<1,l,r);
    if(r>mid)
		sum=max(sum,query(x<<1|1,l,r));
    return sum;
}

2. Weight line segment tree

The weighted line segment tree counts the number of each number, which is equivalent to a "bucket". Usually solve the k-th small (big) problem. Support insert operation.

void modify(int x,int k,int cnt)
{
    
    
    tree[x].v+=cnt;//每一个递归到的都结点都会加cnt
    if(tree[x].l==k&&tree[x].r==k)
		return;
    int mid=tree[x].l+tree[x].r>>1;
    if(k<=mid)
		modify(x<<1,k,cnt);
    else
		modify(x<<1|1,k,cnt);
}
int findk(int x,int k)//这里以求k小为例
{
    
    
    if(tree[x].l==tree[x].r)
		return tree[x].l;
    int mid=tree[x].l+tree[x].r>>1;
    if(tree[x<<1].v>=k)//在左子树中
		return findk(x<<1,k);
    else
		return findk(x<<1|1,k-tree[x<<1].v);//减去左子树的个数
}

3. Dynamic open point line segment tree

For dynamic opening, actually set the left and right to a non-fixed value. When a new point comes, apply for a new point, saving memory.

void modify(int &x,int u,int v,int l,int r)
{
    
    
    if(!tree[x].num)
		tree[x].num=x=++cnt;//一个新的点
    if(l==u&&r==u)
    {
    
    
		tree[x].v=v;
		return;
    }
    int mid=l+r>>1;
    if(u<=mid)
        modify(tree[x].l,u,v,l,mid);
    else
        modify(tree[x].r,u,v,mid+1,r);
    tree[x].v=max(tree[tree[x].l].v,tree[tree[x].r].v);
}

Of course, you can also modify the interval

4. Line segment tree merge

The line segment tree is merged, and the data of two line segment trees can be summarized into one line segment tree. But the space complexity is generally high

int merge(int x,int y)
{
    
    
    if(!x||!y)
		return x+y;//两个相加,得到的是有数的那个数,如果都没有就是0
    int u=++cnt;//开新结点
    tree[u].v=tree[x].v+tree[y].v;//合并一个都有数的点
    tree[u].l=merge(tree[x].l,tree[y].l);
    tree[u].r=merge(tree[x].r,tree[y].r);//两个树同位置结点
    return u;
}

5. Persistent line segment tree

The persistent line segment tree is a line segment tree that can save the version of the previous line segment tree.

void modefy(int x,int l,int r,int u,int v)
{
    
    
	++cnt;//新点
	if(l==r)
	{
    
    
		tr[cnt].v=v;
		return cnt;
	}
	int mid=l+r>>1,temp=cnt;
	if(u<=mid)
	{
    
    
		tr[cnt].rson=tr[x].rson;//没变化,直接连边
		tr[cnt].lson=modefy(tr[x].lson,l,mid,u,v);//有变化,开新点
	}
	else
	{
    
    
		tr[cnt].lson=tr[x].lson;//没变化,直接连边
		tr[cnt].rson=modefy(tr[x].rson,mid+1,r,u,v);//有变化,开新点
	}
	return temp;
}

6, zkw line segment tree

7. Two-dimensional line segment tree

8. Segment tree split

9. Line segment tree divide and conquer

10. Scan line method

Will be updated continuously later

Guess you like

Origin blog.csdn.net/weixin_44043668/article/details/106591579