线段树板子封装

区间修改change to,区间查询最小值min

struct segtree
{
    struct node
    {
        int l, r, tag;
        int val;
    };
    vector<node> tr;
    segtree(int n1) : tr((n1 + 10) << 2) {}
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].tag = -inf; //修改值若为负数则要修改,tag的值应在修改范围之外
        if (l == r)
        {
            tr[root].val = a[l]; //初始值
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
    }
    void spread(int p)
    {
        if (tr[p].tag != -inf)
        {
            tr[p << 1].val = tr[p].tag;
            tr[p << 1 | 1].val = tr[p].tag;
            tr[p << 1].tag = tr[p].tag;
            tr[p << 1 | 1].tag = tr[p].tag;
            tr[p].tag = -inf;
        }
    }
    void update(int root, int l, int r, int x)
    {
        if (l <= tr[root].l && r >= tr[root].r)
        {
            tr[root].val = x;
            tr[root].tag = x;
            return;
        }
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        if (l <= mid)
            update(root << 1, l, r, x);
        if (r > mid)
            update(root << 1 | 1, l, r, x);
        tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
    }
    int getmin(int root, int l, int r) //单点更新下的
    {
        if (l <= tr[root].l && r >= tr[root].r)
            return tr[root].val;
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = inf * inf;
        if (l <= mid)
            ans = min(ans, getmin(root << 1, l, r));
        if (r > mid)
            ans = min(ans, getmin(root << 1 | 1, l, r));
        return ans;
    }
};

区间修改change to,区间求和sum

struct segtree
{
    struct node
    {
        int l, r, tag;
        int val;
    };
    vector<node> tr;
    segtree(int n1) : tr((n1 + 10) << 2) {}
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].tag = inf; //设置为一个不可能达到的值
        if (l == r)
        {
            tr[root].val = 0; //初始值
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
    }
    void spread(int p)
    {
        if (tr[p].tag != inf)
        {
            tr[p << 1].val = tr[p].tag * (tr[p << 1].r - tr[p << 1].l + 1);
            tr[p << 1 | 1].val = tr[p].tag * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
            tr[p << 1].tag = tr[p].tag;
            tr[p << 1 | 1].tag = tr[p].tag;
            tr[p].tag = inf;
        }
    }
    void update(int root, int l, int r, int x)
    {
        if (l <= tr[root].l && r >= tr[root].r)
        {
            tr[root].val = x * (tr[root].r - tr[root].l + 1);
            tr[root].tag = x;
            return;
        }
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        if (l <= mid)
            update(root << 1, l, r, x);
        if (r > mid)
            update(root << 1 | 1, l, r, x);
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
    }
    int getsum(int root, int l, int r) //单点更新下的
    {
        if (l <= tr[root].l && r >= tr[root].r)
            return tr[root].val;
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = 0;
        if (l <= mid)
            ans = (ans + getsum(root << 1, l, r));
        if (r > mid)
            ans = (ans + getsum(root << 1 | 1, l, r));
        return ans;
    }
};

区间加减add,区间求和sum

struct segtree
{
    struct node
    {
        int l, r, tag;
        int val;
    };
    vector<node> tr;
    segtree(int n1) : tr((n1 + 10) << 2) {}
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].tag = 0; // add的初始值为0
        if (l == r)
        {
            tr[root].val = 0; //初始值
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
    }
    void spread(int p)
    {
        if (tr[p].tag != 0)
        {
            tr[p << 1].val += tr[p].tag * (tr[p << 1].r - tr[p << 1].l + 1);
            tr[p << 1 | 1].val += tr[p].tag * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
            tr[p << 1].tag += tr[p].tag;
            tr[p << 1 | 1].tag += tr[p].tag;
            tr[p].tag = 0;
        }
    }
    void update(int root, int l, int r, int x)
    {
        if (l <= tr[root].l && r >= tr[root].r)
        {
            tr[root].val += x * (tr[root].r - tr[root].l + 1);
            tr[root].tag += x;
            return;
        }
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        if (l <= mid)
            update(root << 1, l, r, x);
        if (r > mid)
            update(root << 1 | 1, l, r, x);
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
    }
    int getsum(int root, int l, int r) //单点更新下的
    {
        if (l <= tr[root].l && r >= tr[root].r)
            return tr[root].val;
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = 0;
        if (l <= mid)
            ans = (ans + getsum(root << 1, l, r));
        if (r > mid)
            ans = (ans + getsum(root << 1 | 1, l, r));
        return ans;
    }
};

区间加减add,区间最小值min

struct segtree
{
    struct node
    {
        int l, r, tag;
        int val;
    };
    vector<node> tr;
    segtree(int n1) : tr((n1 + 10) << 2) {}
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].tag = 0; // add的初始值为0
        if (l == r)
        {
            tr[root].val = 0; //初始值
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
    }
    void spread(int p)
    {
        if (tr[p].tag != 0)
        {
            tr[p << 1].val += tr[p].tag;
            tr[p << 1 | 1].val += tr[p].tag;
            tr[p << 1].tag += tr[p].tag;
            tr[p << 1 | 1].tag += tr[p].tag;
            tr[p].tag = 0;
        }
    }
    void update(int root, int l, int r, int x)
    {
        if (l <= tr[root].l && r >= tr[root].r)
        {
            tr[root].val += x;
            tr[root].tag += x;
            return;
        }
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        if (l <= mid)
            update(root << 1, l, r, x);
        if (r > mid)
            update(root << 1 | 1, l, r, x);
        tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
    }
    int getmin(int root, int l, int r) //单点更新下的
    {
        if (l <= tr[root].l && r >= tr[root].r)
            return tr[root].val;
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = inf * inf;
        if (l <= mid)
            ans = min(ans, getmin(root << 1, l, r));
        if (r > mid)
            ans = min(ans, getmin(root << 1 | 1, l, r));
        return ans;
    }
};

区间加、乘,区间求和(取模) 

struct segtree
{
    struct node
    {
        int l, r, val, tag1, tag2;
    };
    const int mod1; //不取模时可设成ll_max
    vector<node> tr;
    segtree(int n1, int mo) : mod1(mo), tr((n1 + 10) << 2) {}
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].tag1 = 0; // add的初始值为0
        tr[root].tag2 = 1; //乘法初始值为1
        if (l == r)
        {
            tr[root].val = a[l]; //初始值
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        tr[root].val = (tr[root << 1].val + tr[root << 1 | 1].val) % mod1;
    }
    void spread(int p)
    {
        if (tr[p].tag2 != 1)
        {
            tr[p << 1].val = (tr[p << 1].val * tr[p].tag2) % mod1;
            tr[p << 1 | 1].val = (tr[p << 1 | 1].val * tr[p].tag2) % mod1;
            tr[p << 1].tag2 = (tr[p << 1].tag2 * tr[p].tag2) % mod1;
            tr[p << 1 | 1].tag2 = (tr[p << 1 | 1].tag2 * tr[p].tag2) % mod1;
            tr[p << 1].tag1 = (tr[p << 1].tag1 * tr[p].tag2) % mod1;
            tr[p << 1 | 1].tag1 = (tr[p << 1 | 1].tag1 * tr[p].tag2) % mod1;
            tr[p].tag2 = 1;
        }
        if (tr[p].tag1 != 0)
        {
            tr[p << 1].val = (tr[p << 1].val + tr[p].tag1 * (tr[p << 1].r - tr[p << 1].l + 1)) % mod1;
            tr[p << 1 | 1].val = (tr[p << 1 | 1].val + tr[p].tag1 * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1)) % mod1;
            tr[p << 1].tag1 = (tr[p << 1].tag1 + tr[p].tag1) % mod1;
            tr[p << 1 | 1].tag1 = (tr[p << 1 | 1].tag1 + tr[p].tag1) % mod1;
            tr[p].tag1 = 0;
        }
    }
    void update(int root, int l, int r, int x, int y)
    {
        if (tr[root].l >= l && tr[root].r <= r)
        {
            tr[root].val = (tr[root].val * y) % mod1;
            tr[root].val = (tr[root].val + x * (tr[root].r - tr[root].l + 1)) % mod1;
            tr[root].tag1 = ((tr[root].tag1 * y) + x) % mod1;
            tr[root].tag2 = (tr[root].tag2 * y) % mod1;
            return;
        }
        spread(root);
        int mid = (tr[root].r + tr[root].l) >> 1;
        if (l <= mid)
            update(root << 1, l, r, x, y);
        if (r > mid)
            update(root << 1 | 1, l, r, x, y);
        tr[root].val = (tr[root << 1].val + tr[root << 1 | 1].val) % mod1;
    }
    int getsum(int root, int l, int r) //单点更新下的
    {
        if (tr[root].l >= l && tr[root].r <= r)
            return tr[root].val % mod1;
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = 0;
        if (l <= mid)
            ans = (ans + getsum(root << 1, l, r)) % mod1;
        if (r > mid)
            ans = (ans + getsum(root << 1 | 1, l, r)) % mod1;
        return ans;
    }
};

单点修改,区间取模,区间求和O(n * logn * loga)

势能线段树:某个值最多能修改常数次,故区间修改时只需判断当前区间内有无需要修改的数,有则暴力修改即可

const int maxn = 100010;
int a[maxn];
struct segtree
{
    struct node
    {
        int l, r, tag;
        int val;
    };
    vector<node> tr;
    segtree(int n1) : tr((n1 + 10) << 2) {}
    void push_up(int root)
    {
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
        tr[root].tag = max(tr[root << 1].tag, tr[root << 1 | 1].tag);
    }
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        if (l == r)
        {
            tr[root].val = a[l]; //初始值
            tr[root].tag = a[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        push_up(root);
    }
    void update1(int root, int l, int r, int mod) //区间取模
    {
        if (tr[root].l == tr[root].r)
        {
            tr[root].val %= mod;
            tr[root].tag = tr[root].val;
            return;
        }
        int mid = (tr[root].l + tr[root].r) >> 1;
        if (l <= mid && tr[root << 1].tag >= mod) //势能线段树修改条件
            update1(root << 1, l, r, mod);
        if (r > mid && tr[root << 1 | 1].tag >= mod) //势能线段树修改条件
            update1(root << 1 | 1, l, r, mod);
        push_up(root);
    }
    void update2(int root, int l, int r, int x) //单点修改
    {
        if (tr[root].l == tr[root].r)
        {
            tr[root].val = tr[root].tag = x;
            return;
        }
        int mid = (tr[root].r + tr[root].l) >> 1;
        if (l <= mid)
            update2(root << 1, l, r, x);
        if (r > mid)
            update2(root << 1 | 1, l, r, x);
        push_up(root);
    }
    int getsum(int root, int l, int r) //区间求和
    {
        if (l <= tr[root].l && r >= tr[root].r)
            return tr[root].val;
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = 0;
        if (l <= mid)
            ans = (ans + getsum(root << 1, l, r));
        if (r > mid)
            ans = (ans + getsum(root << 1 | 1, l, r));
        return ans;
    }
};

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值