• zkw线段树


    zkw线段树是对普通线段树的常熟优化版本,$≈$树状数组的常数。

    同时普通线段树是近似完全二叉树,而zkw线段树是满二叉树,且普通线段树自上而下访问,zkw线段树先找到叶子节点,自下而上进行访问。

    那么易得建树

    void Build () {
        for (M = 1; M <= N + 1; M <<= 1);
        
        for (int i = M + 1; i <= M + N; i ++)
            Tree[i].val = A[i - M];
        for (int i = M - 1; i >= 1; i --)
            Tree[i].val = Tree[i << 1].val + Tree[i << 1 | 1].val;
    }

    对于区间修改或查询,我们假定此时区间为$[L, R]$,那么令$s = L - 1$,$t = R + 1$(需找到叶子节点编号),同时向上跳,且满足:若$s$所在为左子节点,则修改其右子节点,反之不进行操作;同理若t所在为右子节点,则修改其左子节点,反之不进行操作,并且结束条件为s与t成为兄弟。

    可以发现,依据这样的规则$s$和$t$会遍历普通线段树上所有需进行修改的节点,并且冗余的节点是不会被修改访问到的。

    那么先进行较简单的区间加减,及区间求和操作。

    对于无法下传的懒标记,令其为永久性标记即可。

    void Modify (int L, int R, LL k) {
        LL lnum = 0, rnum = 0, nnum = 1; // 记录已覆盖叶子节点数(即原序列上的节点数)
        int s, t;
        for (s = L + M - 1, t = R + M + 1; s ^ t ^ 1; s >>= 1, t >>= 1, nnum <<= 1) { // s ^ t ^ 1用于判断父节点是否相同
            Tree[s].val += lnum * k; // 覆盖这一半应当覆盖的区间(此处只会修改到线段树中覆盖了当前区间的节点,因为否则lnum / rnum就会为0)
            Tree[t].val += rnum * k;
            
            if (~ s & 1) {
                Tree[s ^ 1].val += nnum * k; // 修改另一半应当覆盖的区间
                Tree[s ^ 1].lazy += k; // 打永久性懒标记
                lnum += nnum;
            }
            if (t & 1) {
                Tree[t ^ 1].val += nnum * k;
                Tree[t ^ 1].lazy += k;
                rnum += nnum;
            }
        }
        
        for (; s; s >>= 1, t >>= 1) { // 剩余祖先处的修改
            Tree[s].val += k * lnum;
            Tree[t].val += k * rnum;
        }
    }

    区间求和大致一致。

    LL Query (int L, int R) {
        LL ans = 0;
        LL lnum = 0, rnum = 0, nnum = 1;
        int s, t;
        for (s = L + M - 1, t = R + M + 1; s ^ t ^ 1; s >>= 1, t >>= 1, nnum <<= 1) {
            if (Tree[s].lazy)
                ans += Tree[s].lazy * lnum; // 如果不在路径上,lnum / rnum为0,不会加上冗余节点
            if (Tree[t].lazy)
                ans += Tree[t].lazy * rnum;
            
            if (~ s & 1) {
                ans += Tree[s ^ 1].val; // 此处要加因为访问不到
                lnum += nnum;
            }
            if (t & 1) {
                ans += Tree[t ^ 1].val;
                rnum += nnum;
            }
        }
        
        for (; s; s >>= 1, t >>= 1) { // 剩余节点处理
            if (Tree[s].lazy)
                ans += Tree[s].lazy * lnum;
            if (Tree[t].lazy)
                ans += Tree[t].lazy * rnum;
        }
        
        return ans;
    }

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    typedef long long LL;
    
    const int MAXN = 1e05 + 10;
    
    struct Node {
        LL val;
        LL lazy;
        
        Node () {
            val = 0;
            lazy = 0;
        }
    } ;
    
    Node Tree[MAXN << 2];
    
    int N, Q, M;
    
    LL A[MAXN]; 
    
    void Build () {
        for (M = 1; M <= N + 1; M <<= 1);
        
        for (int i = M + 1; i <= M + N; i ++)
            Tree[i].val = A[i - M];
        for (int i = M - 1; i >= 1; i --)
            Tree[i].val = Tree[i << 1].val + Tree[i << 1 | 1].val;
    }
    
    void Modify (int L, int R, LL k) {
        LL lnum = 0, rnum = 0, nnum = 1;
        int s, t;
        for (s = L + M - 1, t = R + M + 1; s ^ t ^ 1; s >>= 1, t >>= 1, nnum <<= 1) {
            Tree[s].val += lnum * k;
            Tree[t].val += rnum * k;
            
            if (~ s & 1) {
                Tree[s ^ 1].val += nnum * k;
                Tree[s ^ 1].lazy += k;
                lnum += nnum;
            }
            if (t & 1) {
                Tree[t ^ 1].val += nnum * k;
                Tree[t ^ 1].lazy += k;
                rnum += nnum;
            }
        }
        
        for (; s; s >>= 1, t >>= 1) {
            Tree[s].val += k * lnum;
            Tree[t].val += k * rnum;
        }
    }
    
    LL Query (int L, int R) {
        LL ans = 0;
        LL lnum = 0, rnum = 0, nnum = 1;
        int s, t;
        for (s = L + M - 1, t = R + M + 1; s ^ t ^ 1; s >>= 1, t >>= 1, nnum <<= 1) {
            if (Tree[s].lazy)
                ans += Tree[s].lazy * lnum;
            if (Tree[t].lazy)
                ans += Tree[t].lazy * rnum;
            
            if (~ s & 1) {
                ans += Tree[s ^ 1].val;
                lnum += nnum;
            }
            if (t & 1) {
                ans += Tree[t ^ 1].val;
                rnum += nnum;
            }
        }
        
        for (; s; s >>= 1, t >>= 1) {
            if (Tree[s].lazy)
                ans += Tree[s].lazy * lnum;
            if (Tree[t].lazy)
                ans += Tree[t].lazy * rnum;
        }
        
        return ans;
    }
    
    LL getnum () {
        LL num = 0;
        char ch = getchar ();
        
        while (ch < '0' || ch > '9')
            ch = getchar ();
        while (ch >= '0' && ch <= '9')
            num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();
        
        return num;    
    }
    
    int main () {
        N = getnum (), Q = getnum ();
        
        for (int i = 1; i <= N; i ++)
            A[i] = getnum ();
        
        Build ();
        
        for (int i = 1; i <= Q; i ++) {
            int opt;
            opt = getnum ();
            
            if (opt == 1) {
                int x, y, k;
                x = getnum (), y = getnum (), k = getnum ();
                
                Modify (x, y, k);
            }
            else {
                int x, y;
                x = getnum (), y = getnum ();
                
                LL ans = Query (x, y);
                
                printf ("%lld
    ", ans);
            }
        }
        
        return 0;
    }
    
    /*
    5 5
    1 5 4 2 3
    2 2 4
    1 2 3 2
    2 3 4
    1 1 5 1
    2 1 4
    */
    zkw线段树(区间加、区间和)
  • 相关阅读:
    持续集成 最佳实践 研讨会(1月25日 广州)
    Selenium自动化测试项目案例实践公开课
    自动化测试管理平台ATMS(V2.0.3_8.28)下载
    自动化测试管理平台ATMS(V2.0.2_8.19)下载
    最近的免费软件测试课程
    Ranorex入门指南
    圆满完成Selenium自动化测试周末班培训课程!
    自动化测试管理平台ATMS(V2.0.1_8.12)下载
    GradNet: Gradient-Guided Network for Visual Object Tracking阅读笔记
    Distilling Object Detectors with Fine-grained Feature Imitation阅读笔记
  • 原文地址:https://www.cnblogs.com/Colythme/p/9823129.html
Copyright © 2020-2023  润新知