zoukankan      html  css  js  c++  java
  • 专题1.5

    专题1.5 - 写个线段树板子

    线段树什么功能就不需要多说了,这边主要是讲讲(lazy)标记的作用。

    普通的线段树,修改的效率为(Omicron(nlog n)),查询效率为(Omicron(nlog n)),修改的效率甚至比直接修改还慢(当然直接修改就没法维护线段树了),那么怎么可以提高修改的效率?

    这里需要引入(lazy)标记的概念,具体原理如下:

    1.修改时,如果修改范围恰好为当前区间范围,停止向下搜索,打上(lazy)标记。

    2.修改时,如果范围并非恰好,需要向下传递一次(lazy)标记。

    3.查询时,优先向下传递(lazy)标记。

    这边给出两个模板:

    洛谷P3372

    #include <bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define ppb pop_back
    #define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
    const int maxn = 1e5 + 10;
    int n, m;
    ll tmp[maxn], a[4 * maxn], lazy[4 * maxn];
    using namespace std;
    void build(int o, int l, int r)
    {
        if (l == r)
        {
            a[o] = tmp[l];
            return;
        }
        int mid = (l + r) / 2;
        int ls = 2 * o;
        int rs = 2 * o + 1;
        build(ls, l, mid);
        build(rs, mid + 1, r);
        a[o] = a[ls] + a[rs];
    }
    void pushdown(int o, int l, int r)
    {
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        lazy[ls] += lazy[o];
        lazy[rs] += lazy[o];
        a[ls] += (mid - l + 1) * lazy[o];
        a[rs] += (r - mid) * lazy[o];
        lazy[o] = 0;
    }
    void Update(int o, int l, int r, int ql, int qr, int d)
    {
        if (l == ql && r == qr)
        {
            a[o] += (r - l + 1) * d;
            lazy[o] += d;
            return;
        }
        pushdown(o, l, r);
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        if (mid >= qr)
            Update(ls, l, mid, ql, qr, d);
        else if (mid < ql)
            Update(rs, mid + 1, r, ql, qr, d);
        else
        {
            Update(ls, l, mid, ql, mid, d);
            Update(rs, mid + 1, r, mid + 1, qr, d);
        }
        a[o] = a[ls] + a[rs];
    }
    ll Query(int o, int l, int r, int ql, int qr)
    {
        if (l == ql && r == qr)
            return a[o];
        pushdown(o, l, r);
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        if (mid >= qr)
            return Query(ls, l, mid, ql, qr);
        else if (mid < ql)
            return Query(rs, mid + 1, r, ql, qr);
        else
        {
            return Query(ls, l, mid, ql, mid) + Query(rs, mid + 1, r, mid + 1, qr);
        }
    }
    int main()
    {
        fast;
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            cin >> tmp[i];
        }
        build(1, 1, n);
        int opt;
        while (m--)
        {
            cin >> opt;
            if (opt == 1)
            {
                int l, r, d;
                cin >> l >> r >> d;
                Update(1, 1, n, l, r, d);
            }
            else
            {
                int l, r;
                cin >> l >> r;
                cout << Query(1, 1, n, l, r) << '
    ';
            }
        }
    }
    

    洛谷P3373

    #include <bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define ppb pop_back
    #define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
    const int maxn = 1e5 + 10;
    int p;
    int n, m;
    ll tmp[maxn], a[4 * maxn], add[4 * maxn], mul[4 * maxn];
    using namespace std;
    void build(int o, int l, int r)
    {
        if (l == r)
        {
            a[o] = tmp[l];
            return;
        }
        int mid = (l + r) / 2;
        int ls = 2 * o;
        int rs = 2 * o + 1;
        build(ls, l, mid);
        build(rs, mid + 1, r);
        a[o] = a[ls] + a[rs];
    }
    void pushdown(int o, int l, int r)
    {
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        mul[ls] = mul[ls] * mul[o] % p;
        mul[rs] = mul[rs] * mul[o] % p;
        add[ls] = (add[ls] * mul[o] + add[o]) % p;
        add[rs] = (add[rs] * mul[o] + add[o]) % p;
        a[ls] = (a[ls] * mul[o] + add[o] * (mid - l + 1)) % p;
        a[rs] = (a[rs] * mul[o] + add[o] * (r - mid)) % p;
        add[o] = 0;
        mul[o] = 1;
    }
    void Update_mul(int o, int l, int r, int ql, int qr, int d)
    {
        if (l == ql && r == qr)
        {
            a[o] = a[o] * d % p;
            mul[o] = mul[o] * d % p;
            add[o] = add[o] * d % p;
            return;
        }
        pushdown(o, l, r);
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        if (mid >= qr)
            Update_mul(ls, l, mid, ql, qr, d);
        else if (mid < ql)
            Update_mul(rs, mid + 1, r, ql, qr, d);
        else
        {
            Update_mul(ls, l, mid, ql, mid, d);
            Update_mul(rs, mid + 1, r, mid + 1, qr, d);
        }
        a[o] = (a[ls] + a[rs]) % p;
    }
    void Update_add(int o, int l, int r, int ql, int qr, int d)
    {
        if (l == ql && r == qr)
        {
            a[o] += (r - l + 1) * d;
            add[o] += d;
            return;
        }
        pushdown(o, l, r);
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        if (mid >= qr)
            Update_add(ls, l, mid, ql, qr, d);
        else if (mid < ql)
            Update_add(rs, mid + 1, r, ql, qr, d);
        else
        {
            Update_add(ls, l, mid, ql, mid, d);
            Update_add(rs, mid + 1, r, mid + 1, qr, d);
        }
        a[o] = (a[ls] + a[rs]) % p;
    }
    ll Query(int o, int l, int r, int ql, int qr)
    {
        if (l == ql && r == qr)
            return a[o] % p;
        pushdown(o, l, r);
        int mid = (l + r) / 2;
        int ls = 2 * o, rs = 2 * o + 1;
        if (mid >= qr)
            return Query(ls, l, mid, ql, qr) % p;
        else if (mid < ql)
            return Query(rs, mid + 1, r, ql, qr) % p;
        else
        {
            return (Query(ls, l, mid, ql, mid) + Query(rs, mid + 1, r, mid + 1, qr)) % p;
        }
    }
    int main()
    {
        fast;
        cin >> n >> m >> p;
        for (int i = 1; i <= n; i++)
        {
            cin >> tmp[i];
        }
        build(1, 1, n);
        for (int i = 1; i <= 4 * n; i++)
        {
            add[i] = 0;
            mul[i] = 1;
        }
        int opt;
        while (m--)
        {
            cin >> opt;
            if (opt == 1)
            {
                int l, r, d;
                cin >> l >> r >> d;
                Update_mul(1, 1, n, l, r, d);
            }
            else if (opt == 2)
            {
                int l, r, d;
                cin >> l >> r >> d;
                Update_add(1, 1, n, l, r, d);
            }
            else
            {
                int l, r;
                cin >> l >> r;
                cout << Query(1, 1, n, l, r) << '
    ';
            }
        }
    }
    

    值得注意的是,需要注意向下传递(lazy)的顺序,以及对结果的影响。

  • 相关阅读:
    FastApi
    ceph 分布式存储安装
    Linux的inode的理解
    Linux面试题汇总答案
    五,openstack之nova服务的安装(计算节点)
    四,openstack之nova服务的安装(控制节点)
    三,openstack之glance服务的安装
    二,openstack之keystone的简介与安装
    一,openstack基础服务部署
    Kubernetes学习之路(24)之Prometheus监控
  • 原文地址:https://www.cnblogs.com/endlesskkk/p/15329481.html
Copyright © 2011-2022 走看看