线段树模板
//建树
void built(int root,int left,int right)
{
tree[root].lazy=0;//lazy标志初始化为0
/*记录节点对应的区间
tree[root].left=left;
tree[root].right=right;
*/
if(left==right)//递归出口
{
tree[root]=num[left];
return ;
}
int mid=(left+right)/2;
built(root*2+1,left,mid);//这里线段树根节点从0开始,若从1开始,左右子树的根节点的index要减1
built(root*2+2,mid+1,right);
tree[root].value=tree[root*2+1].value+tree[root*2+2].value;//以sum为value的线段树
tree[root].value=min(tree[root*2+1].value,tree[root*2+2].value);//以最小值为value的线段树
tree[root].value=max(tree[root*2+1].value,tree[root*2+1].value);//以最大值为value的线段树
}
//sum类型树查询
//如果每个树节点都记录了left和right值,则这里的start与end参数可以不需要(其他函数同理)
int query(int root,int start,int end,int left,int right)
{
if(start==end) return tree[root].value;
else if(start>right || end<left) //没有交集
return 0;
else if(start>=left && right>=end) //区间包含
return tree[root].value;
else
{
int mid=(start+end)/2;//如果没有start和end参数 (tree[root].left+tree[root].right)/2
return query(root*2+1,start,mid,left,right)+query(root*2+2,mid+1,end,left,right);
}
}
//sum类型树单点更新
void update(int root,int start,int end,int index,int value) //根据index改value
{
if(start==end)
{
num[index]=value;
tree[root].value=value;
return ;
}
int mid=(start+end)/2;
if(index<=mid) update(root*2+1,start,mid,index,value);
else update(root*2+2,mid+1,end,index,value);
tree[root].value=tree[root*2+1].value+tree[root*2+2].value;
}
void pushdown(int root)//标记下传
{
if(tree[root].lazy)
{
tree[root*2+1].lazy+=tree[root].lazy;
tree[root*2+1].val+=tree[root].lazy;
tree[root*2+2].lazy+=tree[root].lazy;
tree[root*2+2].val+=tree[root].lazy;
tree[root].lazy=0;
}
}
//min 或 max 类型树 查询(min和max大体框架差不多但是具体细节有差别)
int query(int root,int start,int end,int left,int right)
{
if(start>right || end<left) //没有交集
return ;
else if(left>=start && right<=end)//包含在区间内
return tree[root].val;
int mid=(start+end)/2;
if(tree[root].lazy) pushdown(root);
if(right<=mid) return query(root*2+1,start,mid,left,right);
else if(left>mid) return query(root*2+2,mid+1,end,left,right);
else return min(query(root*2+1,start,mid,left,right),query(root*2+2,mid+1,end,left,right));
}
//min类型树 区间更新
void update(int root,int start,int end,int left,int right,int value)
{
if(start>=left && end<=right)
{
tree[root].value+=value;
tree[root].lazy+=value;
return ;
}
if(tree[root].lazy) pushdown(root);
int mid=(start+left)/2;
if(mid>=right) update(root*2+1,start,mid,left,right);
else if(left>mid) update(root*2+2,mid+1,end,left,right);
else
{
update(root*2+1,start,mid,left,right);
update(root*2+2,mid+1,end,left,right);
}
tree[root].value=min(tree[root*2+1].value,tree[root*2+2].value);
}