洛谷P3373 【模板】线段树 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的结果。
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^)
样例说明:
故输出应为17、2(40 mod 38=2)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int n,m,p,judge,x,y,k; 5 long long a[100007]; 6 long long read() 7 { 8 long long x=0,f=1; 9 char ch=getchar(); 10 while(ch>'9'||ch<'0') 11 { 12 if(ch=='-') 13 f=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') 17 { 18 x=x*10+ch-'0'; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 struct node 24 { 25 long long v,mul,add; 26 } st[400007]; 27 void build(int root, int l, int r) 28 { 29 st[root].mul=1; 30 st[root].add=0; 31 if(l==r) 32 st[root].v=a[l]; 33 else 34 { 35 int m=(l+r)/2; 36 build(root*2, l, m); 37 build(root*2+1, m+1, r); 38 st[root].v=st[root*2].v+st[root*2+1].v; 39 } 40 st[root].v%=p; 41 return ; 42 } 43 void pushdown(int root, int l, int r) 44 { 45 int m=(l+r)/2; 46 st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(m-l+1))%p; 47 st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-m))%p; 48 st[root*2].mul=(st[root*2].mul*st[root].mul)%p; 49 st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p; 50 st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p; 51 st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p; 52 st[root].mul=1; 53 st[root].add=0; 54 return ; 55 } 56 void up(int root,int stdl,int stdr,int l,int r,long long k) 57 { 58 if(r<stdl||stdr<l) 59 return ; 60 if(l<=stdl&&stdr<=r) 61 { 62 st[root].v=(st[root].v*k)%p; 63 st[root].mul=(st[root].mul*k)%p; 64 st[root].add=(st[root].add*k)%p; 65 return ; 66 } 67 pushdown(root, stdl, stdr); 68 int m=(stdl+stdr)/2; 69 up(root*2,stdl,m,l,r,k); 70 up(root*2+1,m+1,stdr,l,r,k); 71 st[root].v=(st[root*2].v+st[root*2+1].v)%p; 72 return ; 73 } 74 void date(int root,int stdl,int stdr,int l,int r,long long k) 75 { 76 if(r<stdl||stdr<l) 77 return ; 78 if(l<=stdl&&stdr<=r) 79 { 80 st[root].add=(st[root].add+k)%p; 81 st[root].v=(st[root].v+k*(stdr-stdl+1))%p; 82 return ; 83 } 84 pushdown(root,stdl,stdr); 85 int m=(stdl+stdr)/2; 86 date(root*2,stdl,m,l,r,k); 87 date(root*2+1,m+1,stdr,l,r,k); 88 st[root].v=(st[root*2].v+st[root*2+1].v)%p; 89 return ; 90 } 91 long long query(int root,int stdl,int stdr,int l,int r) 92 { 93 if(r<stdl||stdr<l) 94 return 0; 95 if(l<=stdl&&stdr<=r) 96 return st[root].v; 97 pushdown(root,stdl,stdr); 98 int m=(stdl+stdr)/2; 99 return (query(root*2,stdl,m,l,r)+query(root*2+1,m+1,stdr,l,r))%p; 100 } 101 int main() 102 { 103 n=read(),m=read(),p=read(); 104 for(int i=1; i<=n; i++) 105 a[i]=read(); 106 build(1,1,n); 107 while(m--) 108 { 109 judge=read(); 110 if(judge==1) 111 { 112 x=read(),y=read(),k=read(); 113 up(1,1,n,x,y,k); 114 } 115 else if(judge==2) 116 { 117 x=read(),y=read(),k=read(); 118 date(1,1,n,x,y,k); 119 } 120 else 121 { 122 x=read(),y=read(); 123 printf("%lld\n", query(1,1,n,x,y)); 124 } 125 } 126 return 0; 127 }