线段树

来源:互联网 发布:cocos2dx v3.10 mac 编辑:程序博客网 时间:2024/06/08 12:24

线段树

百度百科:线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为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);    }}


3  更新

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的思想,不用不加



0 0
原创粉丝点击