线段树——区间累加、区间累乘、区间求和
题解:
这道题目的难点在于如何考虑加法和乘法的”兼容“问题
定义两个标记 mul_lazy 和 add_lazy 分别表示加法和乘法
默认乘法优先 :因为算术运算中乘法优先级高,add_lazy标记可能还没有下放,如果默认加法优先,修改mul_lazy可能会导致错误
所以 每次乘的时候,子节点mul_lazy和add_lazy都一起乘父节点的mul_lazy,加的时候 子节点的add_lazy加父节点的add_lazy即可
push_down的更新操作代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct node 2 { 3 int l,r; 4 ll sum,add_lazy,mul_lazy; 5 void update(ll mul,ll add) 6 { 7 if(mul!=1) 8 { 9 mul_lazy=(mul_lazy*mul)%mod; 10 add_lazy=(add_lazy*mul)%mod; 11 sum=(sum*mul)%mod; 12 } 13 if(add) 14 { 15 add_lazy=(add_lazy+add)%mod; 16 sum=(sum+((r-l+1)*add))%mod; 17 } 18 } 19 }tree[maxn<<2];
可以发现上面push_down的更新操作,加法和乘法可以合并
合并代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 int n,a[maxn],q,mod; 6 struct node 7 { 8 int l,r; 9 ll sum,add_lazy,mul_lazy; 10 void update(ll mul,ll add) 11 { 12 sum=(sum*mul+add*(r-l+1))%mod; 13 mul_lazy=(mul_lazy*mul)%mod; 14 add_lazy=(add_lazy*mul+add)%mod; 15 16 } 17 }tree[maxn<<2]; 18 19 void push_up(int x) 20 { 21 tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%mod; 22 } 23 void push_down(int x) 24 { 25 int mul=tree[x].mul_lazy; 26 int add=tree[x].add_lazy; 27 if(mul!=1 || add!=0) 28 { 29 tree[x<<1].update(mul,add); 30 tree[x<<1|1].update(mul,add); 31 tree[x].add_lazy=0; 32 tree[x].mul_lazy=1; 33 } 34 } 35 void build(int x,int l,int r) 36 { 37 tree[x].l=l,tree[x].r=r; 38 tree[x].add_lazy=tree[x].sum=0; 39 tree[x].mul_lazy=1; 40 if(l==r) 41 { 42 tree[x].sum=a[l]; 43 } 44 else 45 { 46 int mid=(l+r)>>1; 47 build(x<<1,l,mid); 48 build(x<<1|1,mid+1,r); 49 push_up(x); 50 } 51 } 52 void update(int x,int l,int r,ll val,int flag) 53 { 54 int L=tree[x].l,R=tree[x].r; 55 56 if(l<=L && R<=r) 57 { 58 if(flag==1)tree[x].update(val,0); 59 else tree[x].update(1,val); 60 } 61 else 62 { 63 push_down(x); 64 int mid=(L+R)>>1; 65 if(mid>=l)update(x<<1,l,r,val,flag); 66 if(mid<r)update(x<<1|1,l,r,val,flag); 67 push_up(x); 68 } 69 } 70 ll query(int x,int l,int r) 71 { 72 int L=tree[x].l,R=tree[x].r; 73 74 if(l<=L && R<=r) 75 { 76 return tree[x].sum%mod; 77 } 78 else 79 { 80 push_down(x); 81 ll ans=0; 82 int mid=(L+R)>>1; 83 if(mid>=l)ans+=query(x<<1,l,r)%mod; 84 if(mid<r)ans+=query(x<<1|1,l,r)%mod; 85 push_up(x); 86 return ans%mod; 87 } 88 89 } 90 int main() 91 { 92 scanf("%d%d%d",&n,&q,&mod); 93 for(int i=1;i<=n;i++) 94 scanf("%d",&a[i]); 95 build(1,1,n); 96 for(int i=1;i<=q;i++) 97 { 98 int l,r,op; 99 ll val; 100 scanf("%d",&op); 101 if(op==1) 102 { 103 scanf("%d%d%lld",&l,&r,&val); 104 update(1,l,r,val,op); 105 } 106 else if(op==2) 107 { 108 scanf("%d%d%lld",&l,&r,&val); 109 update(1,l,r,val,op); 110 } 111 else 112 { 113 scanf("%d%d",&l,&r); 114 printf("%lld\n",query(1,l,r)); 115 } 116 117 118 } 119 return 0; 120 }
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 int n,a[maxn],q,mod; 6 struct node 7 { 8 int l,r; 9 ll sum,add_lazy,mul_lazy; 10 void update(ll mul,ll add) 11 { 12 if(mul!=1) 13 { 14 mul_lazy=(mul_lazy*mul)%mod; 15 add_lazy=(add_lazy*mul)%mod; 16 sum=(sum*mul)%mod; 17 } 18 if(add) 19 { 20 add_lazy=(add_lazy+add)%mod; 21 sum=(sum+((r-l+1)*add))%mod; 22 } 23 ///合并代码 24 /* 25 sum=(sum*mul+add*(r-l+1))%mod; 26 mul_lazy=(mul_lazy*mul)%mod; 27 add_lazy=(add_lazy*mul+add)%mod; 28 */ 29 30 } 31 }tree[maxn<<2]; 32 33 void push_up(int x) 34 { 35 tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%mod; 36 } 37 void push_down(int x) 38 { 39 int mul=tree[x].mul_lazy; 40 int add=tree[x].add_lazy; 41 if(mul!=1 || add!=0) 42 { 43 tree[x<<1].update(mul,add); 44 tree[x<<1|1].update(mul,add); 45 tree[x].add_lazy=0; 46 tree[x].mul_lazy=1; 47 } 48 } 49 void build(int x,int l,int r) 50 { 51 tree[x].l=l,tree[x].r=r; 52 tree[x].add_lazy=tree[x].sum=0; 53 tree[x].mul_lazy=1; 54 if(l==r) 55 { 56 tree[x].sum=a[l]; 57 } 58 else 59 { 60 int mid=(l+r)>>1; 61 build(x<<1,l,mid); 62 build(x<<1|1,mid+1,r); 63 push_up(x); 64 } 65 } 66 void update(int x,int l,int r,ll val,int flag) 67 { 68 int L=tree[x].l,R=tree[x].r; 69 70 if(l<=L && R<=r) 71 { 72 if(flag==1)tree[x].update(val,0); 73 else tree[x].update(1,val); 74 } 75 else 76 { 77 push_down(x); 78 int mid=(L+R)>>1; 79 if(mid>=l)update(x<<1,l,r,val,flag); 80 if(mid<r)update(x<<1|1,l,r,val,flag); 81 push_up(x); 82 } 83 } 84 ll query(int x,int l,int r) 85 { 86 int L=tree[x].l,R=tree[x].r; 87 88 if(l<=L && R<=r) 89 { 90 return tree[x].sum%mod; 91 } 92 else 93 { 94 push_down(x); 95 ll ans=0; 96 int mid=(L+R)>>1; 97 if(mid>=l)ans+=query(x<<1,l,r)%mod; 98 if(mid<r)ans+=query(x<<1|1,l,r)%mod; 99 push_up(x); 100 return ans%mod; 101 } 102 103 } 104 int main() 105 { 106 scanf("%d%d%d",&n,&q,&mod); 107 for(int i=1;i<=n;i++) 108 scanf("%d",&a[i]); 109 build(1,1,n); 110 for(int i=1;i<=q;i++) 111 { 112 int l,r,op; 113 ll val; 114 scanf("%d",&op); 115 if(op==1) 116 { 117 scanf("%d%d%lld",&l,&r,&val); 118 update(1,l,r,val,op); 119 } 120 else if(op==2) 121 { 122 scanf("%d%d%lld",&l,&r,&val); 123 update(1,l,r,val,op); 124 } 125 else 126 { 127 scanf("%d%d",&l,&r); 128 printf("%lld\n",query(1,l,r)); 129 } 130 131 132 } 133 return 0; 134 }