1. 程式人生 > 其它 >洛谷P3373 【模板】線段樹 2

洛谷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 }