当前位置: 首页 > news >正文

线段树,单点,区间修改查阅

#PermanentNotes/algorithm

思想

首先关于树有许多类型,这里我们主要首线段树,整体思想就是将一个大区间进行拆分,拆分成各个小区间,在我们进行查找,更新时,就是对区间的查找更新

类型

初始化,构建树

代码

const int Z = 1e7;
const ll INF = 1e18;
const int maxn= 1e5 + 10;
const int maxnn = maxn << 2;
int N, M, E;

ll tree[maxnn];

void build(int l, int r, int k) {
	if (l == r) {
		tree[k] = INF;//在这里,我经常将它的节点写成它的l 
		return;
	}
	int mid = l + r >> 1;
	int lc = k << 1;
	int rc = k << 1 | 1;
	build(l, mid, lc);
	build(mid + 1, r, rc);
	tree[k] = min(tree[lc], tree[rc]);
}

在我们的初始化当中,一定要根据题意,确定我们最开始要初始的值(我们假设我们求的是一个区间最小值,那么将每个区间都初始化为最大值)

单点更新

代码

这里,我们假设求最小值


void pushup(int rt)
{
	tree[rt] = min(tree[rt << 1], tree[rt << 1 | 1]);
}


void update(int pos,ll c,int l,int r,int rt)
{
    if(l==r){
        tree[rt]=min(tree[rt],c);
        return ;
    }

    int m=(l+r)>>1;
    if(pos<=m) update(pos,c,lson);
    if(pos> m) update(pos,c,rson);
    pushup(rt);
}

区间查找

我们假设查找一个区间的最小值

代码

ll query(int L, int R, int l, int r, int rt)
{
	if (L <= l && r <= R) {
		return tree[rt];

	}

	int m = (l + r) >> 1;
	ll ret = inf;
	int lc=rt<<1;
	int rc=rt<<1|1;
	if (L <= m) ret = min(ret, query(L, R, l,m,lc));
	if (R > m) ret = min(ret, query(L, R, m+1,r,rc));
	return ret;
}

区间修改(懒标记法)

每次在进行左右区间(lc,rc)操作之前,先进行pushdown对,对lc,rc操作完毕之后再pushup


typedef long long ll;

#define lc p<<1
#define rc p<<1|1

const int N = 1e5;
int a[N];
struct node {
    int l;
    int r;
    ll sum;
    ll add;
}tr[4 * N];

void pushup(int p) {
    tr[p].sum = tr[lc].sum + tr[rc].sum;
}
void pushdown(int p) {
    if (tr[p].add) {
        tr[lc].sum += (tr[lc].r - tr[lc].l + 1) * tr[p].add;
        tr[rc].sum += (tr[rc].r - tr[rc].l + 1) * tr[p].add;
        tr[lc].add += tr[p].add;
        tr[rc].add += tr[p].add;
        tr[p].add = 0;
    }
}

void build(int p, int l, int r) {
    tr[p] = { l,r,a[l],0 };
    if (l == r)return;
    int m = l + r >> 1;
    build(lc, l, m);
    build(rc, m + 1, r);
    pushup(p);
}

void update(int p, int x, int y, int k) {
    if (x <= tr[p].l && tr[p].r <= y) {
        tr[p].sum += (tr[p].r - tr[p].l + 1) * k;
        tr[p].add += k;
        return;
    }
    int m = tr[p].l + tr[p].r >> 1;
    pushdown(p);
    if (x <= m)update(lc, x, y, k);
    if (m < y)update(rc, x, y, k);
    pushup(p);
}

ll query(int p, int x, int y) {
    if (x <= tr[p].l && tr[p].r <= y)return tr[p].sum;
    int m = tr[p].l + tr[p].r >> 1;
    pushdown(p);
    ll sum = 0;
    if (x <= m)sum += query(lc, x, y);
    if (m < y)sum += query(rc, x, y);
    return sum;
}


推荐视频b站up董晓算法我的算法都是在这儿学的

线段树例题
acwing243
洛谷p3372
洛谷p3373

http://www.dtcms.com/a/106363.html

相关文章:

  • 酶动力学预测工具CataPro安装教程
  • Rabbit:流加密的 “极速赛车手”
  • 单例模式与线程安全
  • 每日算法-250402
  • SESSION_UPLOAD_PROGRESS 的利用
  • Spark、Flink 和 TensorFlow 三大分布式数据处理框架对比
  • 微服务架构技术栈选型避坑指南:10大核心要素深度拆解
  • 供应链中的的“四流合一”
  • 以太网报文结构 via ethernetPacket in CAPL
  • 三轴云台之相机技术篇
  • JavaWeb开发基础知识-Servlet终极入门指南(曼波萌新版)
  • KingbaseES物理备份还原之物理备份
  • 单框架鸿蒙开发
  • 解决报错curl: (35) OpenSSL SSL_connect: 连接被对方重设 in connection to download.docker.com:443
  • JavaScript闭包
  • Python设计模式:责任链模式
  • JAVASE(十三)常用类(二)包装类、工具类Arrays类
  • 【案例分享】江苏某汽车制造厂水冷式制冷站AI节能优化方案
  • LVS-----DR模式
  • JAVA中JVM一次 GC的 流程
  • 电脑屏幕亮度随心控,在Windows上自由调整屏幕亮度的方法
  • 分布式数据一致性场景与方案处理分析|得物技术
  • 谷粒商城:Redisson
  • TiDB 可观测性解读(二)丨算子执行信息性能诊断案例分享
  • Linux网络编程socket服务器端模拟实现
  • JSP 指令
  • Python数据类型-dict
  • 第八届 蓝桥杯 嵌入式 省赛
  • 【ESP32-IDF 笔记】02-LED PWM 配置
  • 运维面试题(ORACLE数据库)--20250401