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);}}
}