lazy法写线段树(区间修改和查询)

hdu1698(区间修改) 传送门

​
#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,c,sum[400005],lazy[400005];
void build(int l,int r,int pos)//建树 
{
	if(l==r)
	{
		sum[pos]=1;
		return;
	}
	int mid=(r+l)/2;
	build(l,mid,pos*2);
	build(mid+1,r,pos*2+1);
	sum[pos]=sum[pos*2]+sum[pos*2+1];
}
void pushdown(int l,int r,int pos)//标记 下传 
{
	if(lazy[pos]!=0)//如果这个点可以被更改 
	{
		int mid=(l+r)/2;
		lazy[pos*2]=lazy[pos*2+1]=lazy[pos];//那么他的俩个儿子也应该被更改,更改的数也就是lazy 
		sum[pos*2]=(mid-l+1)*lazy[pos];//俩个儿子的区间的数不也就是俩个区间乘以lazy 
		sum[pos*2+1]=(r-mid)*lazy[pos];
		lazy[pos]=0;//这个数改过了 
	}
}
void update(int l,int r,int L,int R,int v,int pos)
{
	if(L>=l&&R<=r)//如果这个区间属于要更改的区间 
	{
		lazy[pos]=v;//要更改的数赋给lazy 
		sum[pos]=(R-L+1)*v;//这个区间的数的和不就是长度乘以v 
		return;//表示这个区间被标记完了 可以去上一层了 
	}
	pushdown(L,R,pos);//下传 
	int mid=(R+L)/2;
	if(l<=mid)//如果区间有部分在左区间 
	update(l,r,L,mid,v,pos*2);
	if(r>mid)//如果区间有部分在右区间 
	update(l,r,mid+1,R,v,pos*2+1);
	sum[pos]=sum[pos*2]+sum[pos*2+1];
}
int main()
{
	int t;
	scanf("%d",&t);
	int k=0;
	while(t--)
	{
		memset(sum,0,sizeof(sum));
		memset(lazy,0,sizeof(lazy));
		scanf("%d%d",&n,&m);
		build(1,n,1);
		while(m--)
		{
			scanf("%d%d%d",&a,&b,&c);
			update(a,b,1,n,c,1); 
		}
		 printf("Case %d: The total value of the hook is %d.\n",++k,sum[1]);
	}
	return 0;
}

​

洛谷 线段树模板1 传送门

#include<bits/stdc++.h>
using namespace std;
long long int sum[100000*4], lazy[100000*4],n,m,x,y,z,a[100005],p;
void build(long long int l,long long int r,long long int pos)//建树 
{
	if(r==l)
	{
		sum[pos]=a[l];
		return;
	}
	long long int mid=(r+l)/2;
	build(l,mid,pos*2);
	build(mid+1,r,pos*2+1);
	sum[pos]=sum[pos*2]+sum[pos*2+1];
}
void pushdown(long long int l,long long int r,long long int pos)//下传 
{
	if(lazy[pos]!=0)
	{
		long long int mid=(r+l)/2;
		lazy[pos*2]+=lazy[pos];
		lazy[pos*2+1]+=lazy[pos];
		sum[pos*2]+=(mid-l+1)*lazy[pos];
		sum[pos*2+1]+=(r-mid)*lazy[pos];
		lazy[pos]=0;
	}
}
void update(long long int l,long long int r,long long int L,long long int R,long long int v,long long int pos)//更新 加v 
{
	if(l<=L&&r>=R)
	{
		lazy[pos]+=v;
		sum[pos]+=(R-L+1)*v;
		return;
	}
	long long int mid=(R+L)/2;
	pushdown(L,R,pos);
	if(l<=mid)
	update(l,r,L,mid,v,pos*2);
	if(r>mid)
	update(l,r,mid+1,R,v,pos*2+1);
	sum[pos]=sum[pos*2]+sum[pos*2+1];
}
long long query(long long int l,long long int r,long long int L,long long int R,long long int pos)//查找 
{
	long long res=0;
	if(l<=L&&r>=R)
	return sum[pos];
	long long mid=(L+R)/2;
	pushdown(L,R,pos);
	if(l<=mid)//如果有数在左边的话 左边部分查找 
	res+=query(l,r,L,mid,pos*2);
	if(r>mid)//如果有数在右边 右边部分查找 
	res+=query(l,r,mid+1,R,pos*2+1);
	return res;
}
int main()
{
	scanf("%lld %lld",&n,&m);
	for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
	build(1,n,1);
	while(m--)
	{
		scanf("%lld",&p);
		if(p==1)
		{
			scanf("%lld%lld%lld",&x,&y,&z);
			update(x,y,1,n,z,1);
		}
		else
		{
			scanf("%lld %lld",&x,&y);
			printf("%lld\n",query(x,y,1,n,1));
		}
	}
} 

洛谷 线段树模板二 区间更改的乘法修改和加法修改同时存在 以乘法的优先级更高来处理

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
long long n,m,mod,x,y,z,op,sum[maxn*4],mul[maxn*4],add[maxn*4],a[maxn];
void build(long long l,long long r,long long res)
{
	mul[res]=1;
	add[res]=0;
	if(l==r)
	{
		sum[res]=a[l];
		return;
	}
	long long mid=(l+r)/2;
	build(l,mid,res*2);
	build(mid+1,r,res*2+1);
	sum[res]=sum[res*2]+sum[res*2+1];
	sum[res]%=mod;
}
void pushdown(long long l,long long r,long long res)
{
	long long mid=(l+r)/2;
	sum[res*2]=(sum[res*2]*mul[res]+add[res]*(mid-l+1))%mod;
	sum[res*2+1]=(sum[res*2+1]*mul[res]+add[res]*(r-mid))%mod;
	mul[res*2]=(mul[res*2]*mul[res])%mod;
	mul[res*2+1]=(mul[res*2+1]*mul[res])%mod;
	add[res*2]=(add[res*2]*mul[res]+add[res])%mod;
	add[res*2+1]=(add[res*2+1]*mul[res]+add[res])%mod;
	mul[res]=1;
	add[res]=0;
}
void update1(long long l,long long r,long long res,long long L,long long R,long long k)
{
	if(L<=l&&R>=r)
	{
		sum[res]=(sum[res]*k)%mod;
		mul[res]=(mul[res]*k)%mod;
		add[res]=(add[res]*k)%mod;
		return;
	}
	pushdown(l,r,res);
	long long mid=(l+r)/2;
	if(L<=mid) update1(l,mid,res*2,L,R,k);
	if(R>mid) update1(mid+1,r,res*2+1,L,R,k);
	sum[res]=(sum[res*2]+sum[res*2+1])%mod;
}
void update2(long long l,long long r,long long res,long long L,long long R,long long k)
{
	if(L<=l&&R>=r)
	{
		sum[res]=(sum[res]+k*(r-l+1))%mod;
		add[res]=(add[res]+k)%mod;
		return;
	}
	pushdown(l,r,res);
	long long mid=(l+r)/2;
	if(L<=mid) update2(l,mid,res*2,L,R,k);
	if(R>mid) update2(mid+1,r,res*2+1,L,R,k);
	sum[res]=(sum[res*2]+sum[res*2+1])%mod;
}
long long query(long long l,long long r,long long res,long long L,long long R)
{
	if(L<=l&&R>=r)
	{
		return sum[res];
	}
	pushdown(l,r,res);
	long long mid=(l+r)/2,ans=0;
	if(L<=mid) ans=(ans+query(l,mid,res*2,L,R))%mod;
	if(R>mid) ans=(ans+query(mid+1,r,res*2+1,L,R))%mod;
	return ans%mod;
}
int main()
{

	scanf("%lld%lld",&n,&mod);
	for(long long i=1; i<=n; i++)
		scanf("%lld",&a[i]);
	build(1,n,1);
	scanf("%lld",&m);
	while(m--)
	{
		scanf("%lld",&op);
		if(op==1)
		{
			scanf("%lld%lld%lld",&x,&y,&z);
			update1(1,n,1,x,y,z);
		}
		else if(op==2)
		{
			scanf("%lld%lld%lld",&x,&y,&z);
			update2(1,n,1,x,y,z);
		}
		else
		{
			scanf("%lld%lld",&x,&y);
			long long q=query(1,n,1,x,y);
			printf("%lld\n",q);
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值