线段树是一种基于分治思想的二叉树结构,用于在区间上进行统计。每个节点代表一个区间,对于每个内部节点[l,r](编号p),左子节点代表区间[l,mid](编号p_2),右子节点代表区间[mid+1,r](编号p_2+1).可以用结构体数组保存一棵线段树,数组大小开到N*4
P2068 统计和
定义线段树
struct segment_tree
{
int l,r;
long long sum;
}tree[100010*4];
建树
void build(int p,int l,int r)
{
tree[p].l=l,tree[p].r=r,tree[p].sum=0;
if(l==r) return;//到达根节点
int mid=(l+r)/2;
build(p*2,l,mid);//左子树
build(p*2+1,mid+1,r);//右子树
}
单点修改
void change(int p,int x,int v)
{
if(tree[p].l==tree[p].r)//到达对应单点(左右端点值都为x)
{
tree[p].sum+=v;//修改
return;
}
int mid=(tree[p].l+tree[p].r)/2;
if(x<=mid) change(p*2,x,v);//单点在左子树
else change(p*2+1,x,v);//单点在右子树
tree[p].sum=(tree[p*2].sum+tree[p*2+1].sum);//合并
}
区间查询
假设当前询问的区间为[l,r]
递归到一个区间[tl,tr]时,有四种情况:
-
l < =