线段树——区间累加、区间累乘、区间求和

题目链接

题解:

这道题目的难点在于如何考虑加法和乘法的”兼容“问题

定义两个标记 mul_lazy 和 add_lazy 分别表示加法和乘法

默认乘法优先 :因为算术运算中乘法优先级高,add_lazy标记可能还没有下放,如果默认加法优先,修改mul_lazy可能会导致错误

 

所以 每次乘的时候,子节点mul_lazy和add_lazy都一起乘父节点的mul_lazy,加的时候 子节点的add_lazy加父节点的add_lazy即可

 

push_down的更新操作代码

 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];
View Code

 

可以发现上面push_down的更新操作,加法和乘法可以合并

 

合并代码

  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 }
View Code

 

 

代码:

  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 }
View Code

 

posted @ 2019-09-11 21:24  。小姜  阅读(527)  评论(0编辑  收藏  举报