我原来准备做方差的。。
结果发现不会维护两个标记。。
就是操作变成一个 a*x+b ,每次维护a , b 即可
加的时候a=1 ,b=v
乘的时候a=v ,b=0
1 #include <cstdio> 2 const long long Maxn=100010; 3 4 long long a[Maxn],n,P,l,r,c,m,type; 5 struct Node 6 { 7 long long mul,add,sum,len; 8 }tree[Maxn<<2]; 9 10 inline void Change(long long o,long long mul,long long add) 11 { 12 tree[o].mul=(tree[o].mul*mul)%P; 13 tree[o].add=(tree[o].add*mul+add)%P; 14 tree[o].sum=(tree[o].sum*mul+tree[o].len*add)%P; 15 } 16 inline void push_down(long long o) 17 { 18 Change(o<<1,tree[o].mul,tree[o].add); 19 Change(o<<1|1,tree[o].mul,tree[o].add); 20 tree[o].mul=1; tree[o].add=0; 21 } 22 inline void push_up(long long o) 23 { 24 tree[o].sum=(tree[o<<1].sum+tree[o<<1|1].sum)%P; 25 tree[o].len=tree[o<<1].len+tree[o<<1|1].len; 26 } 27 void Build(long long o,long long l,long long r) 28 { 29 tree[o].mul=1; tree[o].add=0; 30 if (l==r) {tree[o].sum=a[l]; tree[o].len=1; return;} 31 long long mid=(l+r)>>1; 32 Build(o<<1,l,mid),Build(o<<1|1,mid+1,r); 33 push_up(o); 34 } 35 void Mul(long long o,long long l,long long r,long long p,long long q,long long v) 36 { 37 if (l==p && r==q) 38 { 39 Change(o,v,0); 40 return; 41 } 42 push_down(o); 43 long long mid=(l+r)>>1; 44 if (q<=mid) Mul(o<<1,l,mid,p,q,v); 45 if (p>=mid+1) Mul(o<<1|1,mid+1,r,p,q,v); 46 if (p<=mid && q>=mid+1) 47 Mul(o<<1,l,mid,p,mid,v),Mul(o<<1|1,mid+1,r,mid+1,q,v); 48 push_up(o); 49 } 50 void Add(long long o,long long l,long long r,long long p,long long q,long long v) 51 { 52 if (l==p && r==q) 53 { 54 Change(o,1,v); 55 return; 56 } 57 push_down(o); 58 long long mid=(l+r)>>1; 59 if (q<=mid) Add(o<<1,l,mid,p,q,v); 60 if (p>=mid+1) Add(o<<1|1,mid+1,r,p,q,v); 61 if (p<=mid && q>=mid+1) 62 Add(o<<1,l,mid,p,mid,v),Add(o<<1|1,mid+1,r,mid+1,q,v); 63 push_up(o); 64 } 65 long long Sum(long long o,long long l,long long r,long long p,long long q) 66 { 67 if (l==p && r==q) return tree[o].sum; 68 long long mid=(l+r)>>1; 69 push_down(o); 70 if (q<=mid) return Sum(o<<1,l,mid,p,q); 71 if (p>=mid+1) return Sum(o<<1|1,mid+1,r,p,q); 72 if (p<=mid && q>=mid+1) 73 return (Sum(o<<1,l,mid,p,mid)+Sum(o<<1|1,mid+1,r,mid+1,q))%P; 74 } 75 int main() 76 { 77 // freopen("c.in","r",stdin); 78 scanf("%lld%lld",&n,&P); 79 for (long long i=1;i<=n;i++) scanf("%lld",&a[i]); 80 Build(1,1,n); 81 scanf("%lld",&m); 82 for (long long i=1;i<=m;i++) 83 { 84 scanf("%lld",&type); 85 if (type==1) 86 { 87 scanf("%lld%lld%lld",&l,&r,&c); 88 Mul(1,1,n,l,r,c); 89 } 90 if (type==2) 91 { 92 scanf("%lld%lld%lld",&l,&r,&c); 93 Add(1,1,n,l,r,c); 94 } 95 if (type==3) 96 { 97 scanf("%lld%lld",&l,&r); 98 printf("%lld\n",Sum(1,1,n,l,r)); 99 } 100 } 101 return 0; 102 }
线段树
时间: 2024-11-09 19:55:06