线段树如下图所示,是一个二叉搜索树,记录了a到b的一些信息,比如在这里我们记录a到b所有节点数的总和。下图所示:根节点是1-4,这个节点可以分为1-2,3-4两个子节点,同理,子节点继续往下面分裂。
例题:
在示例代码中,
1.a数组存放这个线段树,每个节点的父节点(加)或它前面的兄弟节点(减,有时候找不到,直接找到0,就是没有)可以通过lowbit计算
具体展开关系:1->2;2->4;3->4;4->8;5->6;6->8;7->8;
2.lowbit:
正数与它的负数的与,负数的二进制是正数取反再加一
3.getsum
获取0-t的总和,8(4)记录了0-8的所有值,所以直接可求
7:记录了自己,所以要计算6(记录了5-6),4(0-4)
4.代码贴在这主要为了遇到的时候快速复制粘贴
#include <stdio.h>
#include <string.h>
#include<math.h>
int a[50005];
int n;
int lowbit(int t){
return t&(-t);
}
void insert(int t,int d){
while(t<=n){
a[t]+=d;
t=t+lowbit(t);
}
}
__int64 getsum(int t){
__int64 sum=0;
while(t>0){
sum+=a[t];
t=t-lowbit(t);
}
return sum;
}
int main(){
int T,i,j,k,t;
scanf("%d",&T);
t=0;
while(T--){
memset(a,0,sizeof(a));
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&k);
insert(i,k);
}
char str[10];
scanf("%s",str);
printf("Case %d:\n",++t);
while(strcmp(str,"End")!=0){
int x,y;
scanf("%d%d",&x,&y);
if(strcmp(str,"Query")==0)
printf("%lld\n",getsum(y)-getsum(x-1));
else if(strcmp(str,"Add")==0)
insert(x,y);
else if(strcmp(str,"Sub")==0)
insert(x,-y);
scanf("%s",str);
}
}
return 0;
}