洛谷P3373 【模板】线段树 2

相比模板1,这道题增加了乘法的操作,不难想到打两种标记,一种加法,一种乘法。

打加法标记tag1时,直接加就行了,tag1+=x;

打乘法标记tag2时,tag2*=x,tag1*=tag2,因为之前加的数也要乘进去。

下传标记也是相同的道理。(注意要时不时mod p)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e5+10;
  4 #define ll long long 
  5 struct node{
  6     ll l,r,sum,tag1,tag2;
  7 }t[N<<2];
  8 int n,m,p;
  9 int read(){
 10     int x=0,f=1;char c=getchar();
 11     while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
 12     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
 13     return x*f;
 14 }
 15 
 16 void pushup(int k){
 17     t[k].sum=(t[k<<1].sum+t[k<<1|1].sum)%p;
 18 }
 19 
 20 void build(int k,int l,int r){
 21     t[k].l=l,t[k].r=r;
 22     t[k].tag2=1;
 23     if(l==r){
 24         t[k].sum=read();
 25         return ;
 26     }
 27     int mid=(l+r)>>1;
 28     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
 29     pushup(k);
 30 }
 31 
 32 void pushdown(int k){//乘法优先 
 33     t[k<<1].sum=(t[k<<1].sum*t[k].tag2+(t[k<<1].r-t[k<<1].l+1)*t[k].tag1)%p;
 34     t[k<<1|1].sum=(t[k<<1|1].sum*t[k].tag2+(t[k<<1|1].r-t[k<<1|1].l+1)*t[k].tag1)%p;
 35     
 36     t[k<<1].tag2=(t[k<<1].tag2*t[k].tag2)%p;
 37     t[k<<1|1].tag2=(t[k<<1|1].tag2*t[k].tag2)%p;
 38     
 39     t[k<<1].tag1=(t[k<<1].tag1*t[k].tag2+t[k].tag1)%p;
 40     t[k<<1|1].tag1=(t[k<<1|1].tag1*t[k].tag2+t[k].tag1)%p;
 41     
 42     t[k].tag1=0;
 43     t[k].tag2=1;
 44 }
 45 
 46 void change2(int k,int l,int r,int x){
 47     if(t[k].l>=l && t[k].r<=r){
 48         t[k].sum=(t[k].sum*x)%p;
 49         t[k].tag2=t[k].tag2*x%p;
 50         t[k].tag1=t[k].tag1*x%p;
 51         return ;
 52     }
 53     pushdown(k);
 54     int mid=(t[k].l+t[k].r)>>1;
 55     if(l<=mid) change2(k<<1,l,r,x);
 56     if(r>mid) change2(k<<1|1,l,r,x);
 57     pushup(k);
 58 }
 59 
 60 void change1(int k,int l,int r,int x){
 61     if(t[k].l>=l && t[k].r<=r){
 62         t[k].sum=(t[k].sum+(t[k].r-t[k].l+1)*x)%p;
 63         t[k].tag1=(t[k].tag1+x)%p;
 64         return ;
 65     }
 66     pushdown(k);
 67     int mid=(t[k].l+t[k].r)>>1;
 68     if(l<=mid) change1(k<<1,l,r,x);
 69     if(r>mid) change1(k<<1|1,l,r,x);
 70     pushup(k);
 71 }
 72 
 73 ll query(int k,int l,int r){
 74     if(t[k].l>=l && t[k].r<=r){
 75         return t[k].sum%p;
 76     }
 77     pushdown(k);ll ans=0;
 78     int mid=(t[k].l+t[k].r)>>1;
 79     if(l<=mid) ans=(ans%p+query(k<<1,l,r)%p)%p;
 80     if(r>mid) ans=(ans%p+query(k<<1|1,l,r)%p)%p;
 81     return ans%p;
 82 }
 83 
 84 int main(){
 85     n=read(),m=read(),p=read();
 86     build(1,1,n);
 87     while(m--){
 88         int opt,x,y,z;
 89         opt=read();
 90         if(opt==1){
 91             x=read(),y=read(),z=read();
 92             change2(1,x,y,z);
 93         }
 94         else if(opt==2){
 95             x=read(),y=read(),z=read();
 96             change1(1,x,y,z);
 97         }
 98         else{
 99             x=read(),y=read();
100             cout<<query(1,x,y)<<endl;
101         }
102     }
103 }

 

posted @ 2022-05-28 11:57  YHXo  阅读(29)  评论(0编辑  收藏  举报