线段树动态开点

Posted cutemush

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树动态开点相关的知识,希望对你有一定的参考价值。

//zz https://blog.csdn.net/u012972031/article/details/88751811
//https://www.luogu.org/problemnew/show/P3372

 

#include<cstdio>
#include<iostream>
using namespace std;
const int N=300010;
struct node{
	int ls,rs,lazy;
	long long sum;
}tr[N];
int root=0,cnt=0;
void insert(int &root,int l,int r,int ll,int rr,int x)
{
	if(!root)
	    root=++cnt;
	int b=min(r,rr)-max(l,ll)+1;
	tr[root].sum+=b*x;
	if(l>=ll&&r<=rr)
	{
		tr[root].lazy+=x;
		return;
	}
	int mid=l+r>>1;
	if(ll<=mid)
	   insert(tr[root].ls,l,mid,ll,rr,x);
	if(rr>mid)
	   insert(tr[root].rs,mid+1,r,ll,rr,x);
} 
long long query(int root,int l,int r,int ll,int rr)
{
	if(l>=ll&&r<=rr)
	   return tr[root].sum;
	int mid=l+r>>1;
	if(tr[root].lazy)
	{
		if(!tr[root].ls)
		   tr[root].ls=++cnt;
		tr[tr[root].ls].lazy+=tr[root].lazy;
		tr[tr[root].ls].sum+=tr[root].lazy*(mid-l+1);
		if(!tr[root].rs)
		   tr[root].rs=++cnt;
		tr[tr[root].rs].lazy+=tr[root].lazy;
		tr[tr[root].rs].sum+=tr[root].lazy*(r-mid);
		tr[root].lazy=0;
	}
	long long ans=0;
	if(ll<=mid)
	   ans+=query(tr[root].ls,l,mid,ll,rr);
	if(rr>mid)
	   ans+=query(tr[root].rs,mid+1,r,ll,rr);
	return ans;
}
int main()
{
	int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
	{
        int temp;
        cin>>temp;
        insert(root,1,n,i,i,temp);
    }
    for(int i=1;i<=m;i++)
	{
        int ta,tb,tc,td;
        cin>>ta>>tb>>tc;
        if(ta==1)
		{
            cin>>td;
            insert(root,1,n,tb,tc,td);
        }
		else 
		if(ta==2)
		{
            cout<<query(root,1,n,tb,tc)<<endl;
        }
    }
    return 0;
}

  

以上是关于线段树动态开点的主要内容,如果未能解决你的问题,请参考以下文章

线段树 动态开点

HDU6183 Color it (线段树动态开点)

动态开点线段树

「模板」线段树静态开点(单点+区间修改)动态开点

HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)

HDU - 6183 动态开点线段树 || 令人绝望的线段树