线段树

每个节点运用结构体来存储信息

struct node
{
    ll  l,r,w,f;//l 节点的左端点。r 节点的右端点。w 为节点的和。f 为懒惰标记
} tree[6*1000001];

建树

void build(ll l,ll r,ll k)
{
    tree[k].l=l;//存储左端点
    tree[k].r=r;//存储右端点
    if(l==r)
    {
        scanf("%lld",&tree[k].w);
        return ;
    }
    ll m=(l+r)/2;
    build(l,m,2*k);//建立左子树
    build(m+1,r,2*k+1);//建立右子树
    tree[k].w=tree[2*k].w+tree[2*k+1].w;
}

单点查询

void sum(int k)
{
	if(tree[k].l==tree[k].r)
	{
		p=tree[k].w;
		return ;
	}
	int m=(tree[k].l+tree[k].r)/2;
	if(tree[k].f)
	down(k);
	if(x<=m)
	sum(2*k);
	else 
	sum(2*k+1); 
}

单点修改

void add(ll k)
{
    if(tree[k].l==tree[k].r)
    {
        tree[k].w+=y;
        return ;
    }
    ll m=(tree[k].l+tree[k].r)/2;
    if(tree[k].f) down(k);//若代码没有使用懒惰标记,可以不用加
    if(x<=m)
        add(2*k);
    else
        add(2*k+1);
    tree[k].w=tree[2*k].w+tree[2*k+1].w;
}

区间修改

void add(ll k)
{
    if(x<=tree[k].l&&tree[k].r<=y)
    {
        tree[k].w+=(tree[k].r-tree[k].l+1)*z;//更新节点
        tree[k].f+=z;//更新懒惰数组
        return ;
    }
    ll m=(tree[k].l+tree[k].r)/2;
    if(tree[k].f) down(k);//向下传递懒惰标记
    if(x<=m)
        add(2*k);
    if(y>m)
        add(2*k+1);
    tree[k].w=tree[2*k].w+tree[2*k+1].w;//更新父节点
}

区间查询

void sum(ll k)
{
    if(tree[k].l>=x&&tree[k].r<=y)
    {
        ans+=tree[k].w;
        return ;
    }
    if(tree[k].f)
        down(k);
    ll m=(tree[k].l+tree[k].r)/2;
    if(m>=x)
        sum(2*k);
    if(y>m)
        sum(2*k+1);
}

懒惰数组

void down(ll k)
{
    tree[2*k].f+=tree[k].f;
    tree[2*k+1].f+=tree[k].f;//更新子节点的懒惰数组
    tree[2*k].w+=(tree[2*k].r-tree[2*k].l+1)*tree[k].f;
    tree[2*k+1].w+=(tree[2*k+1].r-tree[2*k+1].l+1)*tree[k].f;//更新节点的和
    tree[k].f=0;//将节点懒惰标记归零。
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值