线段树
百度百科:线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
线段树有两种:一是点更新,另一个是段更新。
一、点更新
1 求和
void pushup(int rt)
{
S[rt] = S[rt << 1] + S[rt << 1 | 1];
}
2 建树
void build(int l, int r, int rt)
{
if(l == r)
{
scanf("%d", &S[rt]);
}
else
{
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
}
void update2(int p, int add, int l, int r, int rt)
{
if(l == r)
S[rt] += add;
else
{
int mid = (l + r) >> 1;
if(p <= mid)
update2(p, add, lson);
else
update2(p, add, rson);
pushup(rt);
}
}
4 查找
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R)
{
return S[rt];
}
int sum = 0;
int mid = (l + r) >> 1;
if(L <= mid)
sum += query(L, R, lson);
if(R >= mid + 1)
sum += query(L, R, rson);
return sum;
}
二、段更新
1 求和
void pushup(long long rt)
{
S[rt] = S[rt << 1] + S[rt << 1 | 1];
}
2 向下加
void pushdown(long long rt, long long len)
{
if(Add[rt])
{
Add[rt << 1] += Add[rt];
Add[rt << 1 | 1] += Add[rt];
S[rt << 1] += Add[rt] * (len - (len >> 1));
S[rt << 1 | 1] += Add[rt] * (len >> 1);
Add[rt] = 0;
}
}3 建树
void build(long long l, long long r, long long rt)
{
Add[rt] = 0;
if(l == r)
{
S[rt] = 0;
return;
}
long long mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
4 更新
void update2(long long L, long long R, long long add, long long l, long long r, long long rt)
{
if(L <= l && r <= R)
{
Add[rt] += add;
S[rt] += (long long)add * (r - l + 1);
return;
}
pushdown(rt, r - l + 1);
long long mid = (l + r) >> 1;
if(L <= mid)
update2(L, R, add, lson);
if(R >= mid +1)
update2(L, R, add, rson);
pushup(rt);
}
5 查找
long long query(long long L, long long R, long long l, long long r, long long rt)
{
if(L <= l && r <= R)
{
return S[rt];
}
pushdown(rt, r - l + 1);
long long sum = 0;
long long mid = (l + r) >> 1;
if(L <= mid)
sum += query(L, R, lson);
if(R >= mid + 1)
sum += query(L, R, rson);
return sum;
}
经典例题
A - Curious Robin Hood LightOJ - 1112 点更新
B - Horrible Queries LightOJ - 1164 段更新
感觉就是模板,段更新利用了lazy的思想,不用不加

被折叠的 条评论
为什么被折叠?



