暑假集训 第四节 线段树

线段树

typedef long long ll;
const int maxn = 1e5 + 5;
int a[maxn];
ll tree[maxn * 4];
int flag[maxn * 4];
/
传入各函数的结点node应该为1(比如下面的代码)。
传入结点为1的关系:
左儿子:2*node
右儿子:2*node+1
如果传入结点为0的话,结点的关系就变成了
左儿子:2*node+1
右儿子:2*node+2

///建树
void build(int *a,int node,int l,int r) 
{
    if (l == r)
    {
        tree[node] = a[l];
        return ;
    }
    int mid = (l + r) / 2;
    build(a, node * 2, l, mid);
    build(a, node * 2 + 1, mid + 1, r);
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
///将下标K的结点flag向下传递
void pushdown(int k, int l, int r)
{
    int mid = (l + r) / 2;
    flag[2 * k] += flag[k];
    tree[2 * k] += ((mid - l) + 1) * (ll)flag[k];
    flag[2 * k + 1] += flag[k];
    tree[2 * k + 1] += (r - mid) * (ll)flag[k];
    flag[k] = 0;
}
///修改X位置的值为num
void updata_single(int node, int l, int r, int x, int num)
{
    if (l == x && r == x)
    {
        tree[node] = num;          //如果是x位置加上num,则这里改为tree[node] += num;
        return;
    }
    int mid = (l + r) / 2;
    if (mid >= x)
        updata_single(node * 2, l, mid, x, num);
    else updata_single(node * 2 + 1, mid + 1, r, x, num);
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
///区间[tl,tr]的值全部加上num
void updata_region(int node, int l, int r, int tl, int tr, int num)
{
    if (tl<=l && r <= tr)
    {
        tree[node] = num * (ll)(r - l + 1);
        flag[node] += num;
        return;
    }
    if (flag[node]) pushdown(node, l, r);
    int mid = (l + r) / 2;
    if (tl <= mid) updata_region(node * 2, l, mid, tl, tr, num);
    if (tr > mid) updata_region(node * 2 + 1, mid + 1, r, tl, tr, num);
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
///查询区间和[tl,tr]
ll query(int node, int l, int r, int tl, int tr)
{
    if (tl<=l && r <= tr) return tree[node];
    if (flag[node]) pushdown(node, l, r);
    ll sum = 0;
    int mid = (l + r) / 2;
    if (tl <= mid) sum += query(node * 2, l, mid, tl, tr);
    if (tr > mid) sum += query(node * 2 + 1, mid + 1, r, tl, tr);
    return sum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值