zoukankan      html  css  js  c++  java
  • 【线段树】

    线段树

    之前对线段树不是很明白

    今天自己重新手写了一份线段树

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    
    const int maxn = 1e6 + 10;
    
    struct Node {
    	int l, r, sum, lz;
    }T[maxn << 2];
    
    
    void push_up(int o) {
    	T[o].sum = T[o << 1].sum + T[o << 1 | 1].sum;
    }
    
    void build(int o, int L, int R) {
    	T[o] = Node{ L,R,0,0 };
    	if (L == R) {
    		cin >> T[o].sum;
    		return;
    	}
    	int mid = L + R >> 1;
    	build(o << 1, L, mid);
    	build(o << 1 | 1, mid + 1, R);
    	push_up(o);
    }
    
    
    void push_down(int o) {
    	if (!T[o].lz)return;
    
    	T[o << 1].lz += T[o].lz;
    	T[o << 1 | 1].lz += T[o].lz;
    
    	T[o << 1].sum += (T[o << 1].r - T[o << 1].l + 1) * T[o].lz;
    	T[o << 1 | 1].sum += (T[o << 1 | 1].r - T[o << 1 | 1].l + 1) * T[o].lz;
    
    	T[o].lz = 0;
    }
    
    void updt(int o, int l, int r, int z) {
    	if (l <= T[o].l && T[o].r <= r) {
    		T[o].lz += z;
    		T[o].sum += z * (T[o].r - T[o].l + 1);
    		return;
    	}
    	push_down(o);
    	int mid = T[o].l + T[o].r >> 1;
    	if (l <= mid) updt(o << 1, l, r, z);
    	if (r > mid) updt(o << 1 | 1, l, r, z);
    	push_up(o);
    }
    
    int query(int o, int l, int r) {
    	if (l <= T[o].l && T[o].r <= r) {
    		return T[o].sum;
    	}
    	push_down(o);
    	int sum = 0, mid = T[o].l + T[o].r >> 1;
    	if (l <= mid)sum += query(o << 1, l, r);
    	if (r > mid)sum += query(o << 1 | 1, l, r);
    	return sum;
    }
    

    要理解这份最原始的线段树代码,首先要明确的是

    • (Lazy) 的含义以及作用范围
    • (sum) 的含义以及作用范围

    (Lazy) 作用范围是当前节点的所有子节点,不包括自己在内

    (sum) 的含义是当前子树之和,包含当前节点在内

    再来看 (push\_down)(push\_up) 两个函数

    void push_up(int o) {
    	T[o].sum = T[o << 1].sum + T[o << 1 | 1].sum;
    }
    

    push_up 是在回溯到根节点的时候,更新当前的 (sum)

    void push_down(int o) {
    	if (!T[o].lz)return;
    	//传递标记
    	T[o << 1].lz += T[o].lz;
    	T[o << 1 | 1].lz += T[o].lz;
    	//作用子节点
    	T[o << 1].sum += (T[o << 1].r - T[o << 1].l + 1) * T[o].lz;
    	T[o << 1 | 1].sum += (T[o << 1 | 1].r - T[o << 1 | 1].l + 1) * T[o].lz;
    
    	T[o].lz = 0;
    }
    

    push_down 是将 (lazy) 标记往下传递,由于 (lazy) 标记的作用范围是所有子节点,所以将标记传递给子节点后,还要将标记作用在两个子节点上。

    在update的时候,路径上的所有点都被push_down过,update完后,根节点的sum值就是全部的和。

  • 相关阅读:
    关于vivado----xdc文件时钟约束的初识
    Xilinx FPGA开发环境vivado使用流程
    GTX_SDI搭建流程
    SDI core端口说明
    Vivado中ILA的使用
    SDI初识
    BeautifulSoup库children(),descendants()方法的使用
    阅读OReilly.Web.Scraping.with.Python.2015.6笔记---BeautifulSoup---findAll
    初次使用CentOs7遇到的问题
    Centos7安装WPS和截图工具shutter
  • 原文地址:https://www.cnblogs.com/sduwh/p/13650327.html
Copyright © 2011-2022 走看看