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

被折叠的 条评论
为什么被折叠?



