线段树练习

线段树与树状数组练习
本文介绍了一个具体的编程问题解决案例,使用树状数组处理动态查询与更新操作,如区间求和和单点增减。通过一个具体示例展示了如何在一系列询问中高效维护数组的状态。

线段树练习(codevs题号:1080)
时间限制: 1 s
空间限制: 128000 KB

题目描述 Description
一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。

输入描述 Input Description
输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。

输出描述 Output Description
共m行,每个整数

样例输入 Sample Input
6

4

5

6

2

1

3

4

1 3 5

2 1 4

1 1 9

2 2 6

样例输出 Sample Output
22

22

数据范围及提示 Data Size & Hint

题解:
虽然名字叫线段练习,但在这里我用树状数组来写它。
很简单,输入,判断询问是增加还是求和,然后分别执行相关语句就是了。更多的解释在代码中。

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,a[100010],c[100010],ans[100010],an=0;
int lowbit(int i)//计算i用2的幂方和表示时,其中的最小幂; 
{
    return i&(-i);
}
void update(int i,int value)
{
    while(i<=n)//更新树状数组的值(包括初始化和后面询问时的改值) 
    {
        c[i]+=value;//无论如何 只改变他“父节点 ”的值
        i+=lowbit(i);
    }
}
int  getsum(int i)//求前i个数的和(就是求前缀和嘛) 
{
    int h=0;
     while(i>=1)
     {
        h+=c[i];
        i-=lowbit(i);
     }
     return h;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        update(i,a[i]);//边输入边初始化这个树状数组 (更新它的值) 
    }
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        int p,x,y;
        cin>>p>>x>>y;
        if(p==1)//判断询问 
        {
            a[x]+=y;
            update(x,y);//更新树状数组 
        }
        else if(p==2)
        {
            an++;
            ans[an]=getsum(y)-getsum(x-1);//求这个区间的和,注意区间是[x-1,y],顺便记录下有多少个询问是求和的。 
        }
    }
    for(int i=1;i<=an;i++)
    {
        cout<<ans[i]<<endl;//输出 
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值