我们对于线段树的区间修改你可以用一个最傻的办法循环进行单点修改(时间复杂度太高十分麻瓜)所以,我们要用一个聪明的做法** 延迟标记**(LAZY)
在限度拿书的“区间查询”指令中,每当遇到被询问区间[l,r]完全覆盖的节点时,可以立即把该节点上存储的信息作为候选答案返回。已经有大佬证明,被询问区间[l,r]在线段树上会被分成O(logN)个小区间(节点)从而在O(logN)的时间内求出答案。
我们在执行修改指令时,同样可以在 L<= Pl <= Pr <= R 的情况下立即返回,只不过在回溯之前向节点P增加一个标记,标识“该节点曾经被修改过,但其子节点尚未被更新”。
如果在后续的指令中,需要从节点P向下递归,我们再检查P是否具有标记。若有标记,就根据标记信息更新P的两个子节点,同时为P的两个子节点增加标记,然后清除P的标记。
也就是说,除了在修改指令中直接划分成的O(logN)个节点之外,对任意给点的修改都延迟到“在后续操作中递归进入他的父亲节点时”再执行。这样一来,每条查询或修改指令的时间复杂度都降低到了O(logN)。这些标记被称为“延迟标记”。延迟标记提供了线段树中从上往下传递信息的方式。这种“延迟”也是设计算法与解决问题的一个重要思路。
附上代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
struct segment_tree{
int l,r;
long long sum,mark;
}tree[maxn*4];
long long a[maxn];
int n,m;
void pushup(int root){
tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
}
void pushdown(int root){
if(tree[root].mark){
tree[root<<1].sum += tree[root].mark*(tree[root<<1]</

线段树在处理区间修改时,通过使用延迟标记(LAZY)策略可以提高效率。当区间[l,r]完全覆盖节点时,直接返回节点信息作为答案,并在回溯前为节点增加标记。后续需要递归时,检查节点是否有标记,有的话更新子节点并传递标记,保证每个操作的时间复杂度为O(logN)。延迟标记是线段树中一种有效的信息传递方式,也是算法设计的重要思路。"
135280184,594666,华为OD真题:剩余银饰重量算法解析与实现,"['华为OD', '算法', '开发语言']
最低0.47元/天 解锁文章
533

被折叠的 条评论
为什么被折叠?



