• [数据结构]线段树


    线段树:这么高大上的名字以前从来不敢想23333.

    线段树主要用于一段区间,其中包括 单点修改、区间修改、单点查询、区间查询,其中可能查询最大值或者一段区间的和。

    它的本质把一段区间划分成一小段一小段。线段树的时间复杂度为O(logn)

    我在想为什么单点是O(n),因为还是空间换时间了。数组不仅记录了单点的值,还记录了一个大段的值。

    在查询的过程中,就不必一个一个点去查询,这样就会快。所以线段树也是一个不稳定的东西。

    刚开始建树。一个一个输入叶子,在更新根的值。

     1 void push_up(int rt) {
     2     tree[rt] = tree[rt<<1] + tree[rt<<1|1];
     3 }
     4 void build(int rt, int l, int r) { // rt节点编号  l是节点维护的区间的左端点 r右端点 
     5     if(l == r) {
     6         scanf("%d", &a[l]);
     7         tree[rt] = a[l];
     8         return ;
     9     }
    10     int m = l+r >> 1;
    11     build(rt<<1, l, m);
    12     build(rt<<1|1, m+1, r);
    13     push_up(rt);
    14 }

    单点修改:

    找到这个点的位置,单点增加。全部更新根的值

    void update(int p, int x, int rt, int l, int r) {
        if(l == r) {
            tree[rt] += x;
            return ;
        }    
        int m = l+r >> 1;
        if(p <= m) update(p, x, rt<<1, l, m);
        else update(p, x, rt<<1|1, m+1, r);
        push_up(rt);
    } 

    区间修改:

    需要用一个lazy标记。

    如果全包围,根的值要更新,lazy标记上。

    如果不是全部包围,那么就要往下更新值,往下放。

    往下放的意思就是 往下面小的区间去更新,把当前的lazy删除,加到下面两个区间的lazy,下面两个区间更新根的值。

    最后再去小区间看一看。

    一直递归到全包围为止。

     1 void push_down(int rt, int len) {
     2     lazy[rt<<1] += lazy[rt];
     3     lazy[rt<<1|1] += lazy[rt];
     4     tree[rt<<1] += (len - (len>>1)) * lazy[rt];
     5     tree[rt<<1|1] += (len>>1) * lazy[rt];
     6     lazy[rt] = 0;
     7 }
     8 void Update(int L, int R, int x, int rt, int l, int r) {
     9     if(L <= l && r <= R) {
    10         tree[rt] += (r-l+1)*x;
    11         lazy[rt] += x;
    12         return ;
    13     }
    14     if(lazy[rt]) push_down(rt, r-l+1);
    15     int m = l+r >> 1;
    16     if(L <= m) Update(L, R, x, rt<<1, l, m);
    17     if(R >m) Update(L, R, x, rt<<1|1, m+1, r);
    18 }

    最后的最后查询啦

    如果全包围,就直接输出。

    不是全包围,有lazy就要往下放。

    再往下找。

    1 int query(int L, int R, int rt, int l, int r) {
    2     if(L <= l && r <= R) return tree[rt];
    3     int m = l+r >> 1;
    4     int ans = 0;
    5     if(lazy[rt]) push_down(rt, r-l+1);
    6     if(L <= m) ans += query(L, R, rt<<1, l, m);
    7     if(R > m) ans += query(L, R, rt<<1|1, m+1, r);
    8     return ans;    
    9 }
    No matter how you feel, get up , dress up , show up ,and never give up.
  • 相关阅读:
    ArcGIS for JavaScript继承TiledMapServiceLayer来实现“动态切图”
    Commvault Oracle备份常用命令
    Commvault逻辑架构及组件说明
    数据保护平台如何为新一代应用,人工智能和数据科学提供动力
    SQL Server SSL/TLS 加密
    curl传递大json文件报错解决方法
    MySQL5.5 安装mcafee mysql-audit插件 不成功
    CentOS 6.5安装配置NFS服务器
    利用dump函数理解oracle如何存储各种类型数据
    xfs文件系统挂载大容量磁盘
  • 原文地址:https://www.cnblogs.com/Kaike/p/10298860.html
Copyright © 2020-2023  润新知