首页 > 其他分享 >01 线段树

01 线段树

时间:2024-04-25 21:45:41浏览次数:19  
标签:01 int 线段 节点 区间 lz void

目录

线段树

简介

  • 线段树(一个二叉树)是一个非常重要的数据结构,利用分治的思想。可以用于维护一些满足结合律区间的信息,例如区间元素之和,区间异或和。
  • 线段树可以实现O(logn)(需要Lazy tag,朴素版只允许单点修改和区间查询)的时间复杂度的区间修改区间查询,与树状数组相比,它更具有通用性,但是常数略大。

节点

线段树由多个节点组成,每个节点包含以下信息

  1. 编号: O
  2. 管辖区间: [st,ed]
  3. 权值: 和/最值/异或和/(等满足性质数据)

加法线段树

前缀和在查询与加法交替出现时复杂度很高,不适用
此处可使用树状数组,但是线段树可拓展性更强

因为线段树一定是二叉树,所以一般利用二叉树编号性质构造整棵树.对于编号为x的节点,左儿子为2x,右儿子为2x+1.所以不需要记录左右儿子,但是也使得需要开四倍n的数组才能存下整棵树,一般以1号节点为根.

树的大小为1时为叶节点,叶节点组成原数组
线段树每次操作从根节点开始,每个节点的管辖区间可以由根算出来s

1. 准备变量

#define int long long
const int N = 2e5+10;
int a[N];//原数组
int n;//原数组大小
int t[N << 2];//开四倍空间,t[x]表示节点x所表示的区间元素大小

2. 上拉操作

purhup(上拉操作)是所有线段树所有操作都需要用到的工具函数,是用儿子信息来更新自己的信息.

void pushup(int o)
{
    t[o] = t[o<<1] + t[0<<1 | 1];//可能不是加法
}

3. 建树

建树采用分治思想, 分别将左右子树建立,然后利用pushup来更新当前节点.

void bulidTree(int s = 1,int e = n,int o = 1)
{
    if(s == e)
    {
        t[o] = a[s];
        return ;
    }
    int mid = s + e >> 1;
    bulidTree(s,mid,o<<1),bulidTree(mid+1,e,o<<1 | 1);
    pushup(o);
}

4. 懒标记

懒标记(lazytag)用于表示某个节点尚未更新给子节点的值, 懒标记是保证线段树的区间修改和区间查询的复杂度正确性的关键.

int lz[N<<2]; 
//lz[o]表示: 节点o还有lazy[o]这么大的一个数字,还没有加给左右儿子. 

当lz[o] == 0,说明当前节点的左右儿子都已经被更新,得到了正确的值,使用懒标记必须配合下放操作

5. 下放操作

pushdown(下放操作)需要三个参数, 分别是当前的操作区间([st,ed])和节点编号(O).

void pushdown(int s,int e,int o)
{
    if(!lz[o])  return ;//如果lz[o] == 0,无需下放
    int mid = s + 1 >> 1,ls = 0<<!,rs = o<<1 | 1;//ls,rs为左右儿子编号
    t[ls] += lz[o] * (mid - s + 1);//可改为updata()
    t[rs] += lz[o] * (e-mid);
    //每个t(区间和)都需要乘上一个区间长度. 
    lz[ls] += lz[o],lz[rs] += lz[o];//标记也要下放
    lz[o] = 0;//lz下放完毕
}

6. 区间修改

将区间[l,r]中的数字都加上x,采用递归形式,当走到了目标区域内,就将对应的t[o]和lz[o]做出修改.
此函数是线段树精髓

void add(int l,int r,int x,int s = 1,int e = n,int o = 1)
{
    if(l <= s && e <= r)
    {
        //当前操作区间已经完全进入目标区间,应该直接被修改并且打算lz标记,不再向下
        t[o] += (e-s+1)*x;
        lz[o] += x;
        return; 
    }
    pushdown(e,s,o);//向下走前,必须下放
    int mid = s + e >> 1;
    if(mid >= l)    add(l,r,x,s,mid,o<<1);//判断是否需要往左走
    if(mid + 1 <= r)    add(l,r,x,mid+1,e,o<<1 | 1);//判断是否需要往右走
    pushup(o);//递归回来,上拉
}

updata

void updata(int s,int e,int o,int x)
{
    t[o] += (e-s+1)*x;
    lz[o] += x;
}

异或线段树

只需要修改"pushup"和"updata"

pushup

将"+"改为"^"即可

void pushup(int o)
{
    t[o] = t[o<<1] ^ t[o<<1 | 1];
}

updata

void updata(int s,int e,int o,int x)
{
    t[o] ^= ((e - s + 1)&1) ? x : 0;// 奇数才异或x
    //因为偶数次异或等同于未操作 
    lz[o] ^= x;
}

最值线段树

updata

将区间[s,e],节点o加上x

void updata(int s,int e,int o,int x)
{
    tmax[o] += x,tmin[o] += x;
    lz[o] += x;
}

pushup

void pushup(int o)
{
    tmax[o] = max(tmax[o<<1],tmax[o<<1 | 1]);
    tmin[o] = min(tmin[o<<1],tmin[o<<1 | 1]);
    lz[o] += x;
}

标签:01,int,线段,节点,区间,lz,void
From: https://www.cnblogs.com/zerocloud01/p/18158685

相关文章

  • [De1CTF 2019]SSRF Me
    [De1CTF2019]SSRFMe整理代码#!/usr/bin/envpython#encoding=utf-8fromflaskimportFlaskfromflaskimportrequestimportsocketimporthashlibimporturllibimportsysimportosimportjsonimportimpimp.reload(sys)app=Flask(__name__)secert_key=......
  • [题解] [NOIP2011 提高组] Mayan 游戏
    [题解][NOIP2011提高组]Mayan游戏题目描述有一个\(7\)行\(5\)列的格子棋盘,有的格子上有方块。方块有重力,即如果一个方块下面没有其他方块,他就会往下掉,直到触底或者下面有方块为止。每个方块都有自己的颜色,如果连着三个竖着或者横着的方块颜色相同,它们就会消除。如果出......
  • [IOI2019] 景点划分
    令人忍俊不禁的是,11月的模拟赛出现了“摩拉克斯”一题,被取之。2月JOISC出现这个模型,被取之。2月模拟赛出现这个模型,被取之。本题再次出现这个模型,被取之。呃呃呃呃呃呃呃呃呃啊。首先进行一些简单的分析:令\(A\leB\leC\),构造\(A,B\)合法的情况即可。并且有\(A\len/......
  • 01、Windows 排查
    Windows分析排查分析排查是指对Windows系统中的文件、进程、系统信息、日志记录等进行检测,挖掘Windows系统中是否具有异常情况1.开机启动项检查一般情况下,各种木马、病毒等恶意程序,都会在计算机开机启动过程中自启动查看开机启动项:1.利用操作系统中的启动菜单(注意有的......
  • P3293 [SCOI2016] 美味
    经典题,\(\rm01Trie\)和主席树的结合。考虑一个没有偏移量的时候如何计算,其实就是一个裸的可持久化\(\rmTrie\)。但是有了偏移量就不一样了,这会导致直接改变\(\rmTrie\)的结构,十分不好做。套路的逐位考虑,从高位枚举到低位。假设当前找到的数为\(\rmret\),考虑到\(i\)......
  • P2024 [NOI2001] 食物链
    Solution:使用拓展域并查集,\(1-n\)表示\(\rmA\)群落,\(n+1-2n\)是\(\rmB\)群落,\(2n+1-3n\)是\(\rmC\)群落那么对于操作一,我们首先判断\(x\)是否吃了\(y\)或\(y\)是否吃了\(x\).若吃了,那么这句话为假若没吃,则将(x,y)(x+n,y+n)(x+2n,y+2n)三条边连......
  • Netfilter漏洞提权利用(CVE-2023-35001)
    前言Netfilter是一个用于Linux操作系统的网络数据包过滤框架,它提供了一种灵活的方式来管理网络数据包的流动。Netfilter允许系统管理员和开发人员控制数据包在Linux内核中的处理方式,以实现网络安全、网络地址转换(NetworkAddressTranslation,NAT)、数据包过滤等功能。漏洞成因在......
  • cf 393017C 石头剪刀布 Metacamp2022-onlineA-dev
     Problem-C-Codeforces 五维的DPg[i][D][r][s][p]i:到了第i个位置D:最后有D个点放在后面r,s,p:已经选择了r,s,p个石头,剪刀,布放到后面 四维的DPf[i][D][r][s][p]i:到了第i个位置D:目前有D个点放在后面r,s,p:已经选择了r,s,p个石头,剪刀,布放到后面其......
  • cf 1601B Frog Traveler Codeforces Round 751 (Div. 1)
     Problem-1601B-Codeforces BFS然后每次上升可以的范围是一个区间,然后每次都遍历这个区间的所有点,那么超时。用set等方式,合并这些区间,之前没遍历过的范围才更新(加入BFS需要遍历的队列里)。但是区间的更新特别容易写错…… 我的代码和造数据1/**2记录两个vi......
  • cf gym101981e Eva and Euro coins
     20182019-acmicpc-asia-nanjing-regional-contest-en.pdf(codeforces.com) 这类字符串的能否从s状态到达t状态的题。还可以删除若干子串后然后比较。感觉是一种套路。 100↔111↔001011↔000↔110 01001↔10010可以移动 用栈,如果找到k个连续相同,然后栈删掉这k......