多标记线段树处理法(洛谷3373,codevs4927)

来源:互联网 发布:up安全卫士炒股软件 编辑:程序博客网 时间:2024/06/01 10:34

1.洛谷P3373线段树2

加法和乘法标记,处理方法:

加法时直接添加标记,乘法时将加法标记也进行修改,在标记下放时,先放乘法(直接乘),再放加法(直接加),放乘法标记时要同时修改加法标记。

#include<iostream>#include<cstdio>#include<cstring>#include<climits>#include<iomanip>#include<cmath>#include<vector>#include<algorithm>using namespace std;#define ll long longll read(){ll w=1,q=0;char ch=' ';while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();if(ch=='-')w=-1,ch=getchar();while(ch>='0'&&ch<='9')q=(ll)q*10+ch-'0',ch=getchar();return (ll)w*q;}int n,m;ll mod;ll a[100005],sum[400005],mul[400005],laz[400005];void up(int i){sum[i]=(sum[(i<<1)]+sum[(i<<1)|1])%mod;}void pd(int i,int s,int t){int l=(i<<1),r=(i<<1)|1,mid=(s+t)>>1;if(mul[i]!=1){mul[l]*=mul[i];mul[l]%=mod;mul[r]*=mul[i];mul[r]%=mod;laz[l]*=mul[i];laz[l]%=mod;laz[r]*=mul[i];laz[r]%=mod;sum[l]*=mul[i];sum[l]%=mod;sum[r]*=mul[i];sum[r]%=mod;mul[i]=1;}if(laz[i]){sum[l]+=laz[i]*(mid-s+1);sum[l]%=mod;sum[r]+=laz[i]*(t-mid);sum[r]%=mod;laz[l]+=laz[i];laz[l]%=mod;laz[r]+=laz[i];laz[r]%=mod;laz[i]=0;}return;}void build(int s,int t,int i){mul[i]=1;if(s==t){sum[i]=a[s];return;}int mid=(s+t)>>1;build(s,mid,i<<1);build(mid+1,t,(i<<1)|1);up(i);}void chen(int l,int r,int s,int t,int i,ll z){int mid=(s+t)>>1;if(l<=s&&t<=r){mul[i]*=z;mul[i]%=mod;laz[i]*=z;laz[i]%=mod;sum[i]*=z;sum[i]%=mod;return;}pd(i,s,t);if(mid>=l)chen(l,r,s,mid,(i<<1),z);if(mid+1<=r)chen(l,r,mid+1,t,(i<<1)|1,z);up(i);}void add(int l,int r,int s,int t,int i,ll z){int mid=(s+t)>>1;if(l<=s&&t<=r){sum[i]+=z*(t-s+1);sum[i]%=mod;laz[i]+=z;laz[i]%=mod;return;}pd(i,s,t);if(mid>=l)add(l,r,s,mid,(i<<1),z);if(mid+1<=r)add(l,r,mid+1,t,(i<<1)|1,z);up(i);}ll getans(int l,int r,int s,int t,int i){int mid=(s+t)>>1;ll tot=0;if(l<=s&&t<=r){return sum[i];}pd(i,s,t);if(mid>=l)tot+=getans(l,r,s,mid,(i<<1));tot%=mod;if(mid+1<=r)tot+=getans(l,r,mid+1,t,(i<<1)|1);return tot%mod;}int main(){int i,j,x,y,bh;ll z;n=read();m=read();mod=read();for(i=1;i<=n;i++)a[i]=read();build(1,n,1);for(i=1;i<=m;i++){bh=read();if(bh==1){x=read();y=read();z=read();chen(x,y,1,n,1,z);}else if(bh==2){x=read();y=read();z=read();add(x,y,1,n,1,z);}else if(bh==3){x=read();y=read();printf("%lld\n",getans(x,y,1,n,1));}}   return 0;} 

2.codevs4927线段树练习5

加法标记和区间赋值标记,修改区间赋值标记时将加法标记变成0,修改加法标记时直接改。下放时先放区间赋值标记,同时把儿子的加法标记变为0,再下放加法标记。

#include<iostream>#include<cstdio>#include<cstring>#include<climits>#include<iomanip>#include<cmath>#include<vector>#include<algorithm>using namespace std;#define ll long longconst int SN=400005;ll read(){char ch=' ';ll w=1,q=0;while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();if(ch=='-')w=-1,ch=getchar();while(ch>='0'&&ch<='9')q=(ll)q*10+ch-'0',ch=getchar();return (ll)w*q;}int n,m;ll a[100005],sum[SN],maxx[SN],minn[SN],se[SN],laz[SN];void up(int i){int l=(i<<1),r=(i<<1)|1;sum[i]=sum[l]+sum[r];maxx[i]=max(maxx[l],maxx[r]);minn[i]=min(minn[l],minn[r]);}void pd(int i,int s,int t){int l=(i<<1),r=(i<<1)|1,mid=(s+t)>>1;if(se[i]>=0){//如果有add标记,说明是set后面的sum[l]=(ll)(mid-s+1)*se[i];sum[r]=(ll)(t-mid)*se[i];maxx[l]=se[i];maxx[r]=se[i];minn[l]=se[i];minn[r]=se[i];laz[l]=0;laz[r]=0;se[l]=se[i];se[r]=se[i];se[i]=-1;}if(laz[i]){sum[l]+=(ll)(mid-s+1)*laz[i];sum[r]+=(ll)(t-mid)*laz[i];maxx[l]+=laz[i];maxx[r]+=laz[i];minn[l]+=laz[i];minn[r]+=laz[i];laz[l]+=laz[i];laz[r]+=laz[i];laz[i]=0;}}void build(int s,int t,int i){se[i]=-1;if(s==t){sum[i]=maxx[i]=minn[i]=a[s];return;}int mid=(s+t)>>1;build(s,mid,(i<<1));build(mid+1,t,(i<<1)|1);up(i);}void add(int l,int r,int s,int t,int i,ll z){if(l<=s&&t<=r){sum[i]+=(ll)z*(t-s+1);maxx[i]+=z;minn[i]+=z;laz[i]+=z;return;}pd(i,s,t);int mid=(s+t)>>1;if(mid>=l)add(l,r,s,mid,(i<<1),z);if(mid+1<=r)add(l,r,mid+1,t,(i<<1)|1,z);up(i);}void chan(int l,int r,int s,int t,int i,ll z){if(l<=s&&t<=r){sum[i]=(ll)z*(t-s+1);maxx[i]=z;minn[i]=z;laz[i]=0;se[i]=z;return;}pd(i,s,t);int mid=(s+t)>>1;if(mid>=l)chan(l,r,s,mid,(i<<1),z);if(mid+1<=r)chan(l,r,mid+1,t,(i<<1)|1,z);up(i);}ll getsum(int l,int r,int s,int t,int i){if(l<=s&&t<=r)return sum[i];pd(i,s,t);int mid=(s+t)>>1;ll tot=0;if(mid>=l)tot+=getsum(l,r,s,mid,(i<<1));if(mid+1<=r)tot+=getsum(l,r,mid+1,t,(i<<1)|1);return tot;}ll getmin(int l,int r,int s,int t,int i){if(l<=s&&t<=r)return minn[i];pd(i,s,t);int mid=(s+t)>>1;ll tot=LLONG_MAX;if(mid>=l)tot=getmin(l,r,s,mid,(i<<1));if(mid+1<=r)tot=min(tot,getmin(l,r,mid+1,t,(i<<1)|1));return tot;}ll getmax(int l,int r,int s,int t,int i){if(l<=s&&t<=r)return maxx[i];pd(i,s,t);int mid=(s+t)>>1;ll tot=LLONG_MIN;if(mid>=l)tot=getmax(l,r,s,mid,(i<<1));if(mid+1<=r)tot=max(tot,getmax(l,r,mid+1,t,(i<<1)|1));return tot;}int main(){int i,j,x,y;char ch;ll z;n=read();m=read();for(i=1;i<=n;i++)a[i]=read();build(1,n,1);for(i=1;i<=m;i++){ch=' ';while(ch<'a'||ch>'z')ch=getchar();if(ch=='a'){x=read();y=read();z=read();add(x,y,1,n,1,z);}else if(ch=='s'){ch=getchar();if(ch=='e'){x=read();y=read();z=read();chan(x,y,1,n,1,z);}else {x=read();y=read();printf("%lld\n",getsum(x,y,1,n,1));}}else if(ch=='m'){ch=getchar();if(ch=='i'){x=read();y=read();printf("%lld\n",getmin(x,y,1,n,1));}else {x=read();y=read();printf("%lld\n",getmax(x,y,1,n,1));}}}   return 0;} 


1 0
原创粉丝点击