每个树存放的事左右端点的的总和,然后再递归往下分成更小的区间,根据着2*t是下一层节点的节点端点是(left,left+right)/2);2*t+1是右节点的区间是(left+right)/2+1,right);
而更新的时候就是把点当成是(x,x)这样的区间然后去寻找它所在区间的叶子节点,然后回溯把所有祖先的区间都更新了,然后即使查找的了,当你查找的区间是(l,r)时,你先是从最大的区间开始去查找也就是从节点等于一开始查找看是否与所求的区间相等,不等时有三种可能就是在左右节点或者是左右节点的区间各有一半,然后就分开讨论。
#include<stdio.h>
#include<string.h>
#define mid(x,y) (x+y)/2
int v,b;
int a[500005],ans,cnt;
struct app
{
int left,right;
int sum;
}tree[500000];
void build_tree(int left,int right,int t) //建树,l,r是区间的左右端点数,t是每次从从1开始然后繁衍儿子
{
int x;
tree[t].left=left;
tree[t].right=right;
tree[t].sum=0;
if(left==right)
{ //当它已经是叶子了不能在繁衍了就开始回溯让它的所有祖先都加上儿子(敌营)的人数
while(t!=0)
{
tree[t].sum+=a[left];
t/=2; //下一个祖先
}
return ;
}
x=mid(left,right);
build_tree(left,x,2*t); //对每个区间不断的递归让它们能不断分离下去,注意哦,这里是不断找出每个区间的左区间,直到找完了再开始从头找右节点
build_tree(x+1,right,2*t+1);
}
void updata_tree(int left,int right,int t) //更新线段树,先找到所更新点的叶子,然后再把此点和所有的祖先区间都更新
{
if(tree[t].left==left&&tree[t].right==right)
{
while(t!=0)
{
tree[t].sum+=cnt;
t/=2;
}
return ;
}
int x=mid(tree[t].left,tree[t].right);
if(x>=right) // 分到的点可以锁定在右边的区间所以,关键在2*t着才是代表在右边
updata_tree(left,right,2*t);
else if(x+1<=left)
updata_tree(left,right,2*t+1);
else
{
updata_tree(left,x,2*t);
updata_tree(x+1,right,2*t+1);
}
}
void query_tree(int left,int right,int t) //查找区间如果是在区间里面的就直接把和加上,如果是是在左右区间的中间那就分开加直到你加到你查找的区间被包含在现有的区间内,就结束了然后把你所经历的区间的值加起来就是结果了
{
if(tree[t].left==left&&tree[t].right==right)
{
ans+=tree[t].sum;
return ;
}
int x=mid(tree[t].left,tree[t].right);
if(x>=right)
{
query_tree(left,right,2*t);
}
else if(x+1<=left)
query_tree(left,right,2*t+1);
else
{
query_tree(left,x,2*t);
query_tree(x+1,right,2*t+1);
}
}
int main()
{
int t,n,i,j;
scanf("%d",&t);
for(i=1;i<=t;i++)
{
printf("Case %d:\n",i);
scanf("%d",&n);
memset(a,0,sizeof(a));
for(j=1;j<=n;j++)
scanf("%d",&a[j]);
build_tree(1,n,1);
char sh[10];
while(1)
{
scanf("%s",sh);
if(sh[0]=='E')
break;
if(sh[0]=='A')
{
scanf("%d%d",&v,&cnt);
updata_tree(v,v,1);
}
if(sh[0]=='Q')
{
scanf("%d%d",&v,&b);
ans=0;
query_tree(v,b,1);
printf("%d\n",ans);
}
if(sh[0]=='S')
{
scanf("%d%d",&v,&cnt);
cnt=-cnt;
updata_tree(v,v,1);
}
}
}
return 0;
}