(模板)线段树2
作者:互联网
题目描述
如题,已知一个数列,你需要进行下面三种操作:
1.将某区间每一个数乘上x
2.将某区间每一个数加上x
3.求出某区间每一个数的和
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出格式:
输出包含若干行整数,即为所有操作3的结果。
N<=100000,M<=100000
- 注意:
- 先加后乘,乘法标记要初始化为1,k可能是负数,所以最好+s,再%s
代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cctype> 5 using namespace std; 6 7 inline int read() 8 { 9 int x(0),f(1); char ch; 10 while(!isdigit(ch=getchar())) if(ch=='-') f=-1; 11 while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 12 return f*x; 13 } 14 #define res register int 15 typedef long long LL; 16 const int N=100000+5; 17 struct SegTree{ 18 int l,r; LL val,add,mul; 19 #define l(x) tr[x].l 20 #define r(x) tr[x].r 21 #define val(x) tr[x].val 22 #define mul(x) tr[x].mul 23 #define add(x) tr[x].add 24 #define len(x) (tr[x].r-tr[x].l+1) 25 }tr[N<<2]; 26 int a[N],n,m,s; 27 28 inline void push_up(int p) 29 { 30 val(p)=(val(p<<1)+val(p<<1|1))%s; 31 } 32 33 inline void build(int p,int l,int r) 34 { 35 mul(p)=1; 36 l(p)=l; r(p)=r; 37 if(l==r) { val(p)=a[l]; return ;} 38 int mid=(l+r)>>1; 39 build(p<<1,l,mid); build(p<<1|1,mid+1,r); 40 push_up(p); 41 } 42 43 inline void push_down(int p) 44 { 45 if(add(p)||mul(p)!=1) 46 { 47 val(p<<1)= (val(p<<1)*mul(p) + add(p)*len(p<<1)+s)%s; 48 val(p<<1|1)=(val(p<<1|1) * mul(p) + add(p)*len(p<<1|1)+s)%s; 49 mul(p<<1)= (mul(p) * mul(p<<1)+s)%s; 50 mul(p<<1|1)=(mul(p) * mul(p<<1|1)+s)%s; 51 add(p<<1)= (add(p<<1) * mul(p) + add(p)+s)%s; 52 add(p<<1|1)=(add(p<<1|1)*mul(p) + add(p)+s)%s; 53 add(p)=0; mul(p)=1; 54 } 55 } 56 57 inline void change1(int p,int l,int r,int d) 58 { 59 if(l<=l(p) && r(p)<=r) { 60 val(p)=(val(p)*d)%s; 61 mul(p)=(mul(p)*d)%s; 62 add(p)=(add(p)*d)%s; 63 return ; 64 } 65 push_down(p); 66 int mid=(l(p)+r(p))>>1; 67 if(l<=mid) change1(p<<1,l,r,d); 68 if(r>mid) change1(p<<1|1,l,r,d); 69 push_up(p); 70 } 71 72 inline void change2(int p,int l,int r,int d) 73 { 74 if(l<=l(p) && r(p)<=r) { 75 val(p)=(val(p)+(LL)d*len(p))%s; 76 add(p)=(add(p)+d)%s; return ; 77 } 78 push_down(p); 79 int mid=(l(p)+r(p))>>1; 80 if(l<=mid) change2(p<<1,l,r,d); 81 if(r>mid) change2(p<<1|1,l,r,d); 82 push_up(p); 83 } 84 85 LL ask(int p,int l,int r) 86 { 87 if(l<=l(p) && r(p)<=r) return val(p); 88 push_down(p); int mid=(l(p)+r(p))>>1; 89 LL tmp(0); 90 if(l<=mid) tmp+=ask(p<<1,l,r)%s; 91 if(r>mid) tmp+=ask(p<<1|1,l,r)%s; 92 return tmp%s; 93 } 94 int main() 95 { 96 n=read(); m=read(); s=read(); 97 for(res i=1 ; i<=n ; i++) a[i]=read(); 98 build(1,1,n); 99 for(res i=1 ; i<=m ; i++) 100 { 101 int op=read(),x=read(),y=read(); 102 if(op==1) 103 { 104 int z=read(); change1(1,x,y,z); 105 } 106 else if(op==2) 107 { 108 int z=read(); change2(1,x,y,z); 109 } 110 else if(op==3) 111 printf("%lld\n",ask(1,x,y)); 112 } 113 return 0; 114 }View Code
标签:ch,线段,lmid,格式,区间,操作,include,模板 来源: https://www.cnblogs.com/wmq12138/p/10365082.html