线段树(详细注释—pushdown写法)

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
int n,a[M];
struct SegmentTree{
	int l,r;//左右端点 
	int sum;//区间和 
	int lazy;//增量延迟标记 
}tree[M*4];
//建树
void build(int p,int l,int r){//区间编号,区间左端点,区间右端点 
	tree[p].l=l;tree[p].r=r;//标识区间左右端点
	if(l==r){tree[p].sum=a[l];return;} 
	int mid=(l+r)/2;
	build(p*2,l,mid);//递归左半 
	build(p*2+1,mid+1,r);//递归右半 
	//回溯时更新区间附加信息
	tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;//pushup
} 
void print(int p)
{
	cout<<p<<" "<<tree[p].l<<" "<<tree[p].r<<" "<<tree[p].sum<<endl;
	if(tree[p].l==tree[p].r)return;
	print(p*2);
	print(p*2+1);
}
void update(int p,int x,int v){
	if(tree[p].l==tree[p].r){tree[p].sum=v;return;}
	int mid=(tree[p].l+tree[p].r)/2;
	if(x<=mid) update(p*2,x,v);
	else update(p*2+1,x,v); 
	tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
}//单点修改 
/*int query(int p,int l,int r){
	if(l<=tree[p].l&&tree[p].r<=r) return tree[p].sum;
	int mid=(tree[p].l+tree[p].r)/2;
	int val=0; 
	if(l<mid) val+=query(p*2,l,r);//累加左半重叠部分 
	if(r>mid) val+=query(p*2+1,l,r);//累加右半重叠部分 
	return val;
}*///写法1
int query(int p,int l,int r){
	if(l<=tree[p].l&&tree[p].r<=r) return tree[p].sum;
	//pushdown(p);区间增加添加 
	int mid=(tree[p].l+tree[p].r)/2;
	if(r<=mid) return query(p*2,l,r);
	if(l>mid) return query(p*2+1,l,r);
	else return query(p*2,l,r)+query(p*2+1,l,r);
} //写法2 
/*void add(int p,int d){
	tree[p].sum=d*(tree[p].r-tree[p].l+1);
	if(tree[p].l==tree[p].r)return;  
	add(p*2,d);
	add(p*2+1,d);
}*///树的重构 
void pushdown(int p){
	if(tree[p].lazy){//有延迟标记
		//更新左右子节点信息 
		tree[p*2].sum+=tree[p].lazy*(tree[p*2].r-tree[p*2].l+1);
		tree[p*2+1].sum+=tree[p].lazy*(tree[p*2+1].r-tree[p*2+1].l+1);
		//为子节点增加标记
		tree[p*2].lazy+=tree[p].lazy;
		tree[p*2+1].lazy+=tree[p].lazy;
		//清除父节点标记
		tree[p].lazy=0; 
	}
}
void update1(int p,int l,int r,int d){
	if(l<=tree[p].l&&tree[p].r<=r){
		tree[p].sum+=d*(tree[p].r-tree[p].l+1);
		tree[p].lazy+=d;//区间节点打上标记 
		return;
	}
	pushdown(p);//下传延迟标记 
	int mid=(tree[p].l+tree[p].r)/2;
	if(l<=mid) update1(p*2,l,r,d);
	if(r>mid) update1(p*2+1,l,r,d);//更新区间信息
	tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;//更新区间和 
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,1,n);
	//update(1,5,1);
	//print(1);
	update1(1,2,5,1);
	cout<<query(1,2,3)<<endl; 
	print(1);
	return 0;
}
上一篇:vulnhub-DC系列通关记DC2靶机渗透


下一篇:Spring框架——懒惰初始化+@Import