线段树[模板]

来源:互联网 发布:陕西广电网络总公司 编辑:程序博客网 时间:2024/06/09 21:03

前言

线段树是一个非常实用的数据结构, 并且使用频率非常高. 所有操作都能在log时间内完成, 虽然常数要比树状数组大, 但是比起很多平衡树来说常数还是小了不少. 线段树的应用范围很广, 许多操作都能够支持.
关键是, 线段树好写好调, 完全不恶心.
除非操作非常简单, 尽量不要用树状数组. 线段树虽然代码要比树状数组大但还是很好写的, 关键是线段树要比树状数组应用范围广的多. 关于区间操作尽量用线段树.
最后要注意的就是, 能用线段树的千万不要作死去手写平衡树, 尤其是splay.

下面给出Codevs两道最简单的和操作最全的线段树.

Codevs 线段树练习

最简单滴~

#include<stdio.h>const int maxn = 1e5 + 5;typedef long long lnt;int n, q;int a[maxn];struct node{    node *ls, *rs;    lnt sum;    inline void update()    {        sum = ls->sum + rs->sum;    }}pool[maxn * 4], *tail = pool, *root;node* build(int lf, int rg){    node* bt = ++tail;    if(lf == rg)    {        bt->sum = a[lf];        return bt;    }    int mid = (lf + rg) >> 1;    bt->ls = build(lf, mid);    bt->rs = build(mid + 1, rg);    bt->update();    return bt;}void modify(node* bt, int lf, int rg, int pos, int delta){    if(lf == rg)    {        bt->sum += delta;        return;    }    int mid = (lf + rg) >> 1;    if(pos <= mid) modify(bt->ls, lf, mid, pos, delta);    else modify(bt->rs, mid + 1, rg, pos, delta);    bt->update();}lnt query(node* bt, int lf, int rg, int L, int R){    if(L <= lf && rg <= R) return bt->sum;    int mid = (lf + rg) >> 1;    lnt rt = 0;    if(L <= mid) rt += query(bt->ls, lf, mid, L, R);    if(R > mid) rt += query(bt->rs, mid + 1, rg, L, R);    return rt; }int main(){    scanf("%d", &n);    for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]);    root = build(1, n);    scanf("%d", &q);    for (int i = 1; i <= q; ++ i)    {        int opt, l, r;        scanf("%d%d%d", &opt, &l, &r);        if(opt == 1) modify(root, 1, n, l, r);        if(opt == 2) printf("%lld\n", query(root, 1, n, l, r));    }}

Codevs 线段树练习5

注意逻辑关系.

#include<stdio.h>#include<algorithm>using namespace std;typedef long long lnt;const int maxn = 1e5 + 5;const lnt inf = (lnt)1 << 62;int n, m;lnt a[maxn];char ss[maxn];struct node{    node *ls, *rs;    lnt sum, fix, cmax, cmin;    int flag;    inline void pushdown(int lf, int rg)    {        if(flag == 1)// add        {            int mid = (lf + rg) >> 1;            ls->sum += (mid - lf + 1) * fix;             rs->sum += (rg - mid) * fix;            ls->cmax += fix, rs->cmax += fix;            ls->cmin += fix, rs->cmin += fix;             if(!ls->flag) ls->flag = 1;            if(!rs->flag) rs->flag = 1;            ls->fix += fix, rs->fix += fix;        }        if(flag == 2)// val        {            int mid = (lf + rg) >> 1;            ls->sum = (mid - lf + 1) * fix;            rs->sum = (rg - mid) * fix;            ls->cmax = ls->cmin = fix;            rs->cmax = rs->cmin = fix;            ls->flag = rs->flag = 2;            ls->fix = rs->fix = fix;        }        flag = 0, fix = 0;    }    inline void update()    {        sum = ls->sum + rs->sum;        cmax = max(ls->cmax, rs->cmax);        cmin = min(ls->cmin, rs->cmin);    }}pool[maxn * 4], *tail = pool, *root;node* build(int lf, int rg){    node* bt = ++tail;    if(lf == rg)    {        bt->cmax = bt->cmin = bt->sum = a[lf];        bt->flag = bt->fix = 0;        return bt;    }    int mid = (lf + rg) >> 1;    bt->ls = build(lf, mid);    bt->rs = build(mid + 1, rg);    bt->flag = bt->fix = 0;    bt->update();    return bt;}void modify(node* bt, int lf, int rg, int L, int R, lnt delta, int opt){    if(L <= lf && rg <= R)    {        if(opt)        {            bt->flag = 2, bt->fix = delta;            bt->sum = (rg - lf + 1) * delta;             bt->cmax = bt->cmin = delta;        }        else        {            bt->fix += delta;             if(bt->flag != 2) bt->flag = 1;            bt->sum += (rg - lf + 1) * delta;            bt->cmax += delta, bt->cmin += delta;        }         return;    }    bt->pushdown(lf, rg);    int mid = (lf + rg) >> 1;    if(L <= mid) modify(bt->ls, lf, mid, L, R, delta, opt);    if(R > mid) modify(bt->rs, mid + 1, rg, L, R, delta, opt);    bt->update();}lnt query_sum(node* bt, int lf, int rg, int L, int R){    if(L <= lf && rg <= R) return bt->sum;    bt->pushdown(lf, rg);    int mid = (lf + rg) >> 1;    lnt rt = 0;    if(L <= mid) rt += query_sum(bt->ls, lf, mid, L, R);    if(R > mid) rt += query_sum(bt->rs, mid + 1, rg, L, R);    bt->update();    return rt;}lnt query_max(node* bt, int lf, int rg, int L, int R){    if(L <= lf && rg <= R) return bt->cmax;    bt->pushdown(lf, rg);    int mid = (lf + rg) >> 1;    lnt rt1 = 0, rt2 = 0;    if(L <= mid) rt1 = query_max(bt->ls, lf, mid, L, R);    if(R > mid) rt2 = query_max(bt->rs, mid + 1, rg, L, R);    bt->update();    return max(rt1, rt2);}lnt query_min(node* bt, int lf, int rg, int L, int R){    if(L <= lf && rg <= R) return bt->cmin;    bt->pushdown(lf, rg);    int mid = (lf + rg) >> 1;    lnt rt1 = inf, rt2 = inf;    if(L <= mid) rt1 = query_min(bt->ls, lf, mid, L, R);    if(R > mid) rt2 = query_min(bt->rs, mid + 1, rg, L, R);    bt->update();    return min(rt1, rt2);}int main(){    scanf("%d%d", &n, &m);    for (int i = 1; i <= n; ++ i) scanf("%lld", &a[i]);    root = build(1, n);    for (int i = 1; i <= m; ++ i)    {        scanf("%s", ss);        int l, r; lnt val;        scanf("%d%d", &l, &r);        if(ss[0] == 'a')        {            scanf("%lld", &val);            modify(root, 1, n, l, r, val, 0);        }        if(ss[0] == 's' && ss[1] == 'e')        {            scanf("%lld", &val);            modify(root, 1, n, l, r, val, 1);        }        if(ss[0] == 's' && ss[1] == 'u') printf("%lld\n", query_sum(root, 1, n, l, r));        if(ss[0] == 'm' && ss[1] == 'a') printf("%lld\n", query_max(root, 1, n, l, r));        if(ss[0] == 'm' && ss[1] == 'i') printf("%lld\n", query_min(root, 1, n, l, r));    }}
原创粉丝点击