【手敲算法】线段树[模板] 理解到 裸敲

为什么学习线段树 and 算法作用

查询 or 修改 一段区间或者单点,由O(n) 到 O(logn)

算法原理

为了理解一段区间的 数字 修改 和查询的操作

我们每次将一段区间 二分 成两段

如果 需要修改(查询)的区间 包含当前线段,直接对这一段的数据进行 某种操作

如果 需要修改(查询)的区间 覆盖了当前线段的一部分,向下递归 :1.直到完全覆盖——向上返回数据 2.没有覆盖——跳过

每次更新一层的信息,它的父亲节点信息 因为子节点信息改变了,自己也需要updata函数更新一下

如此利用递归原理逐层寻找自己需要的区间,不需要的直接跳过

因为每段区间都是标准二分,所以最多分出 logn 层,递归修改与查询 也就只有 logn 次

这样的修改与查询只能保证到 单点修改 , 区间查询

为了区间修改需要引入一个lazy标记的概念 可以想象成 数学里 的 delta 变量

lazy标记的使用(pushdown 下推,函数名表明它的作用)

第二次覆盖②区间的 (全部or部分) 时,lazy传递到下一层,本层清空,其它区间同理

区间修改代码(这里是区间求和代码)(单点修改,不需要pushdown函数-直接取消即可,pushup是数据合并方式的函数对应需求修改
例如 取max)

#include <bits/stdc++.h>
#define ls (rt << 1)
#define rs (rt << 1 | 1)
using namespace std;

const int maxn = 1e5 + 7;
const int inf = 1e9 + 7;
typedef long long ll;

struct node{
	int l, r;
	int attr;
	int lazy;
}tree[maxn << 2];
void build(int l, int r, int rt){
	tree[rt].l = l;
	tree[rt].r = r;
	tree[rt].lazy = 0;
	int mid = (l + r) >> 1;
	build(l, mid, ls);
	build(mid+1, r, rs);
}

void pushup(int rt){
	tree[rt].attr = tree[ls].attr + tree[rs].attr;
}

void pushdown(int rt){
	tree[ls].lazy += tree[rt].lazy;
	tree[rs].lazy += tree[rt].lazy;
	tree[rt].lazy = 0;
	tree[ls].attr += tree[ls].lazy * (tree[ls].r - tree[ls].l + 1);
	tree[rs].attr += tree[rs].lazy * (tree[rs].r - tree[rs].l + 1);
}

void updata(int l, int r, int L, int R, int v, int rt){
	if(l <= L && R <= r){
		tree[rt].attr += (R - L + 1) * v;
		tree[rt].lazy += v;
		return;
	}
	int mid = (L + R) >> 1;
	pushdown(rt);
	if(l <= mid)	updata(l, r, L, mid, v, ls);
	if(r > mid)	updata(l, r, mid+1, R, v, rs);
	pushup(rt);
}

int query(int l, int r, int L, int R, int rt){
	if(l <= L && R <= r){
		return tree[rt].attr;
	}
	int res = 0;
	int mid = (L + R) >> 1;
	pushdown(rt);
	if(l <= mid)	query(l, r, L, mid, ls);
	if(r > mid)	query(l, r, mid+1, R, rs);
	pushup(rt);
}

int main()
{
	build(1, n, 1);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值