线段树 的单点更新和区间求和

#include <stdio.h>


int sum[100];


void Build(int lift, int right, int rt);
void Updata(int point, int add, int lift, int right, int rt);
int query(int L, int R, int l, int r, int rt);


int main()
{
    Build(1, 8, 1);
    Updata(1, 2, 1, 8, 1);
    printf("%d\n", query(1, 3, 1, 8, 1));
    for (int i = 1; i <= 15; i++)
        printf("%d\n", sum[i]);
    return 0;
}


// 构建一个线段树
void Build(int lift, int right, int rt)
{
    // l 代表构建的左端; r 代表构建的右端; rt 代表当前的结点
    // 一个基准
    if (right == lift) {
        scanf("%d", &sum[rt]);
        return ;
    }


    int m = (lift + right) / 2;
    // 构建左儿子
    Build(lift, m, rt*2);
    // 构建右儿子
    Build(m+1, right, rt*2+1);


    // 构建好左儿子与右儿子之后, 求出双亲
    sum[rt] = sum[rt*2] + sum[rt*2+1];
}


// 更新单点 去加上一个数
void Updata(int point, int add, int lift, int right, int rt)
{
    // point 代表要更新的点; add 代表要加的数;
    // l 代表构建的左端; r 代表构建的右端; rt 代表当前的结点


    // 一个基准
    if (lift == right) {
        sum[rt] += add;
        return ;
    }


    int m = (lift + right) / 2;
    // 开始寻找是区间 : 在左儿子还是 右儿子
    if (point <= m) // 即在左儿子
        Updata(point, add, lift, m, rt*2);
    else
        Updata(point, add, m+1, right, rt*2+1);


    // 还要更新上面的
    sum[rt] = sum[rt*2] + sum[rt*2+1];
}


// 区间求和
int query(int L, int R, int l, int r, int rt)
{
   // L 为要求的区间左端; R 为要求的区间右端;
   // l 为当前函数区间的左端; R 当前函数区间的右端
   int Sum = 0;
   // 一个基准: 找到L R 所对应的区间后返回;
   if (l >= L && r <= R)
        return (Sum += sum[rt]);


   int m = (l + r) / 2;
   if (L <= m)
        Sum += query(L, R, l, m, rt*2);
   if (R > m)
        Sum += query(L, R, m+1, r, rt*2+1);


   return Sum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值