模板 - 数据结构 - 线段树/SegmentTree

struct SegmentTree {
#define ls (o<<1)
#define rs (o<<1|1)
    static const int MAXN = 100000;
    ll a[MAXN + 5];
    ll st[(MAXN << 2) + 5];

    void PushUp(int o) {
        st[o] = st[ls] + st[rs];
    }

    void Build(int o, int l, int r) {
        if(l == r)
            st[o] = a[l];
        else {
            int m = l + r >> 1;
            Build(ls, l, m);
            Build(rs, m + 1, r);
            PushUp(o);
        }
        lazy[o] = 0;
    }

    void Update(int o, int l, int r, int p, ll v) {
        if(l == r) {
            st[o] += v;
            return;
        } else {
            int m = l + r >> 1;
            if(p <= m)
                Update(ls, l, m, p, v);
            if(p >= m + 1)
                Update(rs, m + 1, r, p, v);
            PushUp(o);
        }
    }

    ll Query(int o, int l, int r, int ql, int qr) {
        if(ql <= l && r <= qr) {
            return st[o];
        } else {
            int m = l + r >> 1;
            ll res = 0;
            if(ql <= m)
                res = res + Query(ls, l, m, ql, qr);
            if(qr >= m + 1)
                res = res + Query(rs, m + 1, r, ql, qr);
            return res;
        }
    }
#undef ls
#undef rs
};
struct SegmentTree {
#define ls (o<<1)
#define rs (o<<1|1)
    static const int MAXN = 100000;
    ll a[MAXN + 5];
    ll st[(MAXN << 2) + 5], lazy[(MAXN << 2) + 5];

    void PushUp(int o) {
        st[o] = st[ls] + st[rs];
    }

    void PushDown(int o, int l, int r) {
        if(lazy[o]) {
            lazy[ls] += lazy[o];
            lazy[rs] += lazy[o];
            int m = l + r >> 1;
            st[ls] += lazy[o] * (m - l + 1);
            st[rs] += lazy[o] * (r - m);
            lazy[o] = 0;
        }
    }

    void Build(int o, int l, int r) {
        if(l == r)
            st[o] = a[l];
        else {
            int m = l + r >> 1;
            Build(ls, l, m);
            Build(rs, m + 1, r);
            PushUp(o);
        }
        lazy[o] = 0;
    }

    void Update(int o, int l, int r, int ql, int qr, ll v) {
        if(ql <= l && r <= qr) {
            lazy[o] += v;
            st[o] += v * (r - l + 1);
            return;
        } else {
            PushDown(o, l, r);
            int m = l + r >> 1;
            if(ql <= m)
                Update(ls, l, m, ql, qr, v);
            if(qr >= m + 1)
                Update(rs, m + 1, r, ql, qr, v);
            PushUp(o);
        }
    }

    ll Query(int o, int l, int r, int ql, int qr) {
        if(ql <= l && r <= qr) {
            return st[o];
        } else {
            PushDown(o, l, r);
            int m = l + r >> 1;
            ll res = 0;
            if(ql <= m)
                res = res + Query(ls, l, m, ql, qr);
            if(qr >= m + 1)
                res = res + Query(rs, m + 1, r, ql, qr);
            return res;
        }
    }
#undef ls
#undef rs
};

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/11877098.html

时间: 2024-08-01 16:39:15

模板 - 数据结构 - 线段树/SegmentTree的相关文章

模板 - 数据结构 - 线段树(单点修改)

这里是以区间最大值为例,要修改成其他的运算,注意修改每个函数的运算以及query中返回的无关值. 这里的区间最大值设置的最小元素为-1(在query中表示与当前区间不相交的区间的结果). 注意因为调用的方式传入l与r是(1,n),所以这个线段树(包括a)其实是从1开始计数的. 最后,小心爆MAXM. const int MAXM=200000; int a[MAXM+5],st[(MAXM<<2)+5]; void build(int o,int l,int r){ if(l==r) st[o

Chapter 3. 数据结构 线段树

Chapter 3. 数据结构 线段树 Sylvia's I.单点修改,区间查询. 模板: //单点修改 区间求和 //1操作 单点修改//2操作 区间求和 #include<cstdio> #include<iostream> using namespace std; #define MAXN 500005 int sum[MAXN<<2]; int n,m; void PushUp(int rt){//求和 sum[rt]=sum[rt<<1]+sum[

「模板」 线段树——区间乘 &amp;&amp; 区间加 &amp;&amp; 区间求和

「模板」 线段树--区间乘 && 区间加 && 区间求和 <题目链接> 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long long p; class SegmentTree { private: struct Node { int l,r; long long v,mul,add; Node *c[2]; Node(int l,int r):l(l),r(r),mul(1LL),add(0LL) { c[

【原创】洛谷 LUOGU P3373 【模板】线段树2

P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字的个数.操作的总个数和模数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k 操作2: 格式:2 x

洛谷P3373 【模板】线段树 2

 P3373 [模板]线段树 2 47通过 186提交 题目提供者HansBug 标签 难度提高+/省选- 提交  讨论  题解 最新讨论 为啥WA(TAT) 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字的个数.操作的总个数和模数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4

洛谷P3372 【模板】线段树 1

P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷评测机出问题了吗? 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接

HDU 4902 Nice boat(数据结构-线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c

HDU 1394 Minimum Inversion Number (数据结构-线段树)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9514    Accepted Submission(s): 5860 Problem Description The inversion number of a given number sequence a1, a2, ..., an

洛谷—— P3372 【模板】线段树 1

P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的