蒟蒻的线段树

线段树模板整理

struct node
{
    int l,r;
    ll sum;///(tag)
};
ll a[maxn];
node tr[maxn<<2];

至于为什么数组要开4倍(能用就行)
在这里插入图片描述接下来就是如何建立这个线段树

void build(int x,int l,int r)
{
    tr[x].l=l,tr[x].r=r;
    if(l==r)
    {
        tr[x].sum=a[l];
        return ;
    }
    int mid=l+r>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
}

以及区间查询

ll query(int x,int l,int r)///interval sum
{
    if(tr[x].l==l&&tr[x].r==r)
    {
        return tr[x].sum;
    }
    if(tr[x].tag!=0)///下推lazy_tag(区间更新时使用)
    {
        push_down(x);
    }
    int mid=tr[x].l+tr[x].r>>1;
    if(l>mid) return query(x<<1|1,l,r);
    else if(r<=mid) return query(x<<1,l,r);
    else return query(x<<1,l,mid)+query(x<<1|1,mid+1,r);
}

单点维护

void update(int x/*查找x号元素*/ ,int y ,int node )///单点更新,将x号元素值更新为y
{
    if(tr[node].l==x&&tr[node].r==x)
    {
        tr[node].sum=y;
        return ;
    }
    int mid=tr[node].l+tr[node].y>>1;
    if(x<=mid) update(x,y,node<<1);
    else update(x,y,node<<1|1);
    tree[node].sum=tr[node<<1].sum+tr[node<<1|1].sum;
}

区间维护
不同于单点维护,因为区间维护需要操作的是区间内所有节点,每次都更新的话效率较低,所以需要建立一个lazytag,用来先储存区间的操作,等到查询的时候再并到线段树里
即:如果某个区间内所有点都被增加了相同的值,则在lazytag中做上标记(以及add的值)

struct node
{
    int l,r;
    ll sum,tag;
};
ll a[maxn];
node tr[maxn<<2];

在后续访问到有lazytag的节点时,不用下推lazytag,如果要访问该节点的子节点,仅需要下推到两个子节点

void push_down(int x)
{
    tr[x<<1].sum+=tr[x].tag*(tr[x<<1].r-tr[x<<1].l+1);
    tr[x<<1|1].sum+=tr[x].tag*(tr[x<<1|1].r-tr[x<<1|1].l+1);
    tr[x<<1].tag+=tr[x].tag;
    tr[x<<1|1].tag+=tr[x].tag;
    tr[x].tag=0;
}

以及区间更新函数

void itvupdate(int x,ll num,int l,int r)///interval update
{
    if(l==tr[x].l&&r==tr[x].r)
    {
        tr[x].sum+=(r-l+1)*num;
        tr[x].tag+=num;
        return ;
    }
    if(tr[x].tag!=0)
        push_down(x);
    int mid=tr[x].l+tr[x].r>>1;
    if(l>mid) itvupdate(x<<1|1,num,l,r);
    else if(r<=mid) itvupdate(x<<1,num,l,r);
    else
    {
        itvupdate(x<<1,num,l,mid);
        itvupdate(x<<1|1,num,mid+1,r);
    }
    tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
}

end

粒子生长树的C语言代码可以通过结点和先序遍历的相关引用结合起来实现。下面是一个简单的粒子生长树的C语言代码示例: ```c typedef struct TreeNode *BinTree; struct TreeNode{ int Data; // 存值 BinTree Left; // 左儿子结点 BinTree Right; // 右儿子结点 }; // 先序遍历 void PreOrderTraversal(BinTree BT){ if(BT){ printf("%d ", BT->Data); // 打印根 PreOrderTraversal(BT->Left); // 进入左子树 PreOrderTraversal(BT->Right); // 进入右子树 } } int main(){ BinTree root = (BinTree)malloc(sizeof(struct TreeNode)); root->Data = 1; root->Left = (BinTree)malloc(sizeof(struct TreeNode)); root->Left->Data = 2; root->Right = (BinTree)malloc(sizeof(struct TreeNode)); root->Right->Data = 3; root->Left->Left = (BinTree)malloc(sizeof(struct TreeNode)); root->Left->Left->Data = 4; root->Left->Right = (BinTree)malloc(sizeof(struct TreeNode)); root->Left->Right->Data = 5; printf("先序遍历结果: "); PreOrderTraversal(root); return 0; } ``` 在这个代码示例中,我们定义了一个结点的结构体`TreeNode`,其中包含了数据`Data`和左右子树的指针`Left`和`Right`。然后我们定义了先序遍历的函数`PreOrderTraversal`来遍历树并打印结果。在`main`函数中,我们创建了一个粒子生长树的实例并进行先序遍历输出。 请注意,这只是一个示例,实际的粒子生长树的实现可能会根据具体需求有所不同,需要根据实际情况进行调整和修改。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值