sys学长 ←orz
http://loisys.cc/oi/template/segment_tree/
typedef long long LL;
const int maxx=1e5+2;
//结构体维护区间信息:区间左端点,区间右端点,区间维护的值
struct tree
{
LL v,add;//add是标记
LL l,f
}t[maxx<<1];
int a[maxx];
//建树
void updata(int n)//更新信息
{
t[n].v=t[n<<1].v+t[n<<1|1].v;//两个儿子+=父亲
}
void build(int l,int r,int n)
{
t[n].l=l,t[n].r=r;
int m=l+r>>1;
if(l==r)//若找到叶子节点
{
t[n].v=a[l];
return;
}
//递归处理儿子
build(l,mid,n<<1);
build(mid+1,r,n<<1|1);
updata(n);//回溯更新信息
}
//查询区间和
LL ask_sum(int n,int l,int r)
{
if(l<=t[n]&&r>=t[n].r)
return t[n].v;
LL ans=0;
int mid=t[n].l+t[n].r>>1;
if(l<=mid) ans+=ask_sum(n<<1,l,r);
if(r>mid) ans+=ask_sum(n<<1|1,l,r);
return ans;
}
//单点修改:从根节点找到叶子节点,修改叶子节点的值,回溯时更新即可。
void change(int n,int p,int x)
{
if(t[n].l==t[n].r)
{
t[n].v=x;
return ;
}
if(p<=t[n].l+t[n].r)
chane(n<<1,l,r,s);
else
change(n<<1|1,l,r,s);
updata(n);
}
//区间修改:需打标记add (查询的时候也要记得下放标记!)
void addp(int n,int x)
{//在某个节点上增加标记
t[n].add+=x;
t[n].v+=x*(t[n].r-t[n].l+1);
}
void spread(int n)
{//把标记下传给儿子
LL &ax=t[n].add;
if(ax)
{
addp(n<<1,ax);
addp(n<<1|1,ax);
ax=0;
}
}
void add(int n,int l,int r,LL x)
{
if(l<=t[n].l&&r>=t[n].r)
{
addp(n,x);
return ;
}
int m=(t[n].l+t[n].r)>>1;
spread(n);
if(l<=m) add(l,r,n<<1,x);
if(r>m) add(l,r,n<<1|1,x);
updata(n);
}
int main()
{
.......................
return 0;
}