线段树是一种搜索型二叉树,可以用它来解决一些使用传统方法非常复杂的问题
要实现线段树的应用需要几个模板
struct tree
{
int l, r;
long long n, sum;
} node[maxn << 2];
上述代码主要用来标识需要的变量,可根据题目需要来填写
void build(int l, int r, int i)//建立线段树
{
node[i] = { l,r };
if (l == r)//如果左右边界相等
{
node[i].sum = a[r];
return;
}
int mid = l + r >> 1;
build(l, mid, i << 1);
build(mid + 1, r, i << 1 | 1);//维护的和等于左右边界相加的和
pushup(i);
}
该代码的作用是将数组a中的元素赋到线段树上
void pushup(int i)//合并线段树
{
node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;
}
上述代码用来合并线段树
void modify(int p, int w, int i)//数据修改
{
if (node[i].l == node[i].r && node[i].l == p)//已经找到修改的位置
{
node[i].sum += w;//修改数据
return;
}
int mid = node[i].l + node[i].r >> 1;
if (p <= mid)modify(p, w, i << 1);//如果在mid的左边
else modify(p, w, i << 1 | 1);//如果在mid的右边
pushup(i);//维护区间和
}
当需要对其中某个元素进行修改时,使用该函数可以找到元素的位置并进行修改,增加时输入为(p,w,i),减时为(p,-w,i)
int read(int l, int r, int i)//查询
{
if (l <= node[i].l && node[i].r <= r)return node[i].sum;//如果(l,r)被(x,y)完全覆盖,就返回当前区间和
int mid = node[i].l + node[i].r >> 1, res = 0;
if (l <= mid)res += read(l, r, i << 1);//如果(x,y)在左子树,向左查找
if (r > mid)res += read(l, r, i << 1 | 1);//如果(x,y)在右子树,向右查找
return res;//返回结果
}
当有区间被完全覆盖时就返回该值