线段树模板

 

模板

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define size 
using namespace std;
struct tree{
	int l,r;
	int mx,sum;
}t[size*4];
void build(int p,int l,int r)//建树  下标 左端点 右端点 
{
	t[p].l=l,t[p].r=r;
	if(l==r)
	{
		t[p].mx=a[l],t[p].sum=a[l];
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	t[p].mx=max(t[p*2].mx,t[p*2+1].mx);
	t[p].sum=t[p*2].sum+t[p*2+1].sum;
}
void change(int p,int x,int v)//单点修改 当前下标 要修改的下标 目标值  
{
	if(t[p].l==t[p].r) 
	{
		t[p].mx=v;return;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(x<=mid) change(p*2,x,v);//x属于左儿子 
	else change(p*2+1,x,v);    //x属于右儿子 
	t[p].mx=max(t[p*2].mx,t[p*2+1].mx); 
	t[p].sum=t[p*2].sum+t[p*2+1].sum;
 } 
int ask(int p,int l,int r)//区间查询   
{
	if(l<=t[p].l&&r>=t[p].r) return t[p].mx;
	int mid=(t[p].l+t[p].r)/2;
	int val=-(1<<30);//负无穷大
	if(l<=mid) val=max(val,ask(p*2,l,r));//左子节点重叠
	if(r>mid) val=max(val,ask(p*2+1,l,r));//右子节点重叠
	return val; 
}
int main()
{
	build(1,1,n);//调用入口 
	change(1,x,v);
	cout<<ask(1,l,r)<<endl; 
	return 0;	
} 

带lazy标记的升级版

//by ziwan Catherine
//线段树 
#include<cstdio>  
#include<algorithm>  
#include<cstring>  
#define N  100010
using namespace std;  
//l,r表示cur节点对应的区间
//L,R,x表示要给区间[L,R]增加x
//sum[cur]表示节点cur的和  
int lazy[N],sum[N];
void update(int cur){
	sum[cur]=sum[cur<<1]+sum[cur<<1|1];
}
void pushdown(int cur,int t){//下传标记 当前节点 区间长度
	lazy[cur<<1]+=lazy[cur];
	lazy[cur<<1|1]+=lazy[cur];
	sum[cur<<1]+=lazy[cur]*(t+1>>1);
	sum[cur<<1|1]+=lazy[cur]*(t>>1);
	lazy[cur]=0;
}
void add(int l,int r,int L,int R,int cur,int x){
	if(L<=l&&R>=r){//被完全包含 
		lazy[cur]+=x;
		sum[cur]+=(r-l+1)*x;
		return;
	}
    pushdown(cur,l-r+1);
	int mid=l+r>>1;
	if(L<=mid) add(l,mid,L,R,cur<<1,x);//左儿子中有
	if(R>mid) add(mid+1,r,L,R,cur<<1|1,x);//右儿子中有
	update(cur); 
}
int ask(int l,int r,int L,int R,int cur){
	if(L<=l&&R>=r) return sum[cur];
	pushdown(cur,r-l+1);
	int mid=l+r>>1,ans=0;
	if(L<=mid) ans+=ask(l,mid,L,R,cur<<1);
	if(R>mid) ans+=ask(mid+1,r,L,R,cur<<1|1);
	return ans;
}
int main(){
	add(1,10,1,10,1,2);
	printf("%d\n", ask(1,10,1,9,1));
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值