线段树
推荐博客 :http://www.cnblogs.com/TheRoadToTheGold/p/6254255.html
一、基本概念
1、线段树是一棵二叉搜索树,它储存的是一个区间的信息。
2、每个节点以结构体的方式存储,结构体包含以下几个信息:
区间左端点、右端点;(这两者必有)
这个区间要维护的信息(事实际情况而定,数目不等)。
3、线段树的基本思想:二分。
4、线段树一般结构如图所示:

线段树的基本操作 :
1 . 节点的结构
struct node
{
int l, r;
int w, f;
}tree[eps]
2. 建树
void build(int l, int r, int k){
tree[k].l = l;
tree[k].r = r;
if (tree[k].l == tree[k].r) {
scanf("%d", &tree[k].w);
return;
}
int m = (tree[k].l + tree[k].r) / 2;
build(l, m, 2*k);
build(m+1, r, 2*k+1);
tree[k].w = tree[k].l + tree[k].r;
}
3 . 懒标记下传操作
void down(int k){
tree[2*k].f += tree[k].f;
tree[2*k+1].f += tree[k].f;
tree[2*k].w += (tree[2*k].r - tree[2*k].l + 1)*tree[k].f;
tree[2*k+1].w += (tree[2*k+1].r - tree[2*k+1].l + 1)*tree[k].f;
tree[k].f = 0;
}
4 .单点查询
void ask(int k){
if (tree[k].l == tree[k].r) {
ans = tree[k].w;
return;
}
if (tree[k].f) down(k);
int m = (tree[k].l + tree[k].r) >> 1;
if (x <= m) ask(2*k);
else ask(2*k+1);
}
5 . 单点修改
void add(int k){
if (tree[k].l == tree[k].r){
tree[k].w += y;
return;
}
if (tree[k].f) down(k);
int m = (tree[k].l + tree[k].r) >> 1;
if (x <= m) add(2*k);
else add(2*k+1);
tree[k].w = tree[2*k].w + tree[2*k+1].w;
}
6 . 区间查询
void sum(int k){
if (a >= tree[k].l && b <= tree[k].r){
ans += tree[k].w;
return;
}
if (tree[k].f) down(k);
int m = (tree[k].l + tree[k].r) >> 1;
if (a <= m) sum(2*k);
if (b > m) sum(2*k+1);
}
7 . 区间修改
void change(int k){
if (a >= tree[k].l && b <= tree[k].r){
tree[k].w += (tree[k].r - tree[k].l + 1)*x;
tree[k].f += x;
return;
}
if (tree[k].f) down(k);
int m = (tree[k].l + tree[k].r) >> 1;
if (a <= m) change(2*k);
if (b > m) change(2*k+1);
tree[k].w = tree[2*k].w + tree[2*k+1].w;
}
8 . 区间替换的懒标记下传
void down(int k, int m){
lazy[k<<1] = lazy[k<<1|1] = lazy[k];
sum[k<<1] = (m - (m>>1)) * lazy[k];
sum[k<<1|1] = (m >> 1) * lazy[k];
lazy[k] = 0;
}
9 .区间替换的代码
void change(int l, int r, int k, int pt){
if (x <= l && r <= y){
lazy[k] = pt;
sum[k] = (r - l + 1) * pt;
return;
}
if (lazy[k]) down(k, r - l + 1);
int m = (l + r) >> 1;
if (x <= m) change(lson, pt);
if (y > m) change(rson, pt);
sum[k] = sum[k<<1] + sum[k<<1|1];
}
东北日出西边雨 道是无情却有情

浙公网安备 33010602011771号