线段树———模板

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int const maxn=100010;
int tot=0,a[maxn]={0};
int n,m;
struct treetype
{
int left,right;    //左右区间 
int letr,ritr;    //左右孩子 
int sum;    //区间和 
} t[maxn*2];
void buildtree(int ll,int rr)    //建树 
{
int tur=++tot;    //结点代号 
t[tur].left=ll;    
t[tur].right=rr;
if (ll!=rr-1)
{
t[tur].letr=tot+1;
buildtree(ll,(ll+rr)/2);
t[tur].ritr=tot+1;
buildtree((ll+rr)/2,rr);
t[tur].sum=t[t[tur].letr].sum+t[t[tur].ritr].sum;    
}
else
t[tur].sum=a[ll];
}
void change(int k,int x,int y)    //更改 
{
if (t[k].left==t[k].right-1)
t[k].sum+=y;
else
{
if (x<(t[k].left+t[k].right)/2)
change(t[k].letr,x,y);
if (x>=(t[k].left+t[k].right)/2)
change(t[k].ritr,x,y);
t[k].sum=t[t[k].letr].sum+t[t[k].ritr].sum;
}
}
int summ(int k,int ll,int rr) //求区间和 
{
if (ll<=t[k].left && rr>=t[k].right)    //如果 目前区间 在 要求的区间 内,那么直接返回目前区间和,
return t[k].sum;    //因为 目前区间 的和一定属于 要求的区间和 
int ans=0;    //记录区间和 
if (ll<(t[k].left+t[k].right)/2)
ans+=summ(t[k].letr,ll,rr);    
if (rr>(t[k].left+t[k].right)/2)
ans+=summ(t[k].ritr,ll,rr);
return ans;    //找(n,m)区间和,那么二分查找各个分区间的和,将值返回累加
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
cin>>a[i];
buildtree(1,n+1);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
int c,p,k;
scanf("%d%d%d",&c,&p,&k);
if (c==1)
change(1,p,k);
if (c==2)
printf("%d
",summ(1,p,k+1));    //要给查找的区间加上1,查找n—>m就要查(n,m+1)  
}    //找了半个小时不同TMD !!! 
}  //【1,n)前闭后开
原文地址:https://www.cnblogs.com/xiaoqi7/p/5317005.html