P3373 【模板】线段树 2
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)
分析
线段树维护两个标记,add,mul表示要加的数,和要乘的数。
下传标记时,add也是要乘以mul的。
还有要开longlong qaq
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #define lson l,m,rt<<1 5 #define rson m+1,r,rt<<1|1 6 #define LL long long 7 8 using namespace std; 9 const int N = 500100; 10 LL sum[N],mul[N],add[N]; 11 LL n,m,p; 12 13 inline char nc() { 14 static char buf[100000],*p1,*p2; 15 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 16 } 17 inline LL read() { 18 LL x = 0,f = 1;char ch = nc(); 19 for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f=-1; 20 for (; ch>='0'&&ch<='9'; ch = nc()) x = x*10+ch-'0'; 21 return x * f; 22 } 23 void pushup(int rt) { 24 sum[rt] = (sum[rt<<1] + sum[rt<<1|1]) % p; 25 } 26 void pushdown(int rt,int k) { 27 sum[rt<<1] = (sum[rt<<1]*mul[rt]+add[rt]*(k-k/2))%p; 28 sum[rt<<1|1] = (sum[rt<<1|1]*mul[rt]+add[rt]*(k/2))%p; 29 mul[rt<<1] = (mul[rt<<1]*mul[rt])%p; 30 mul[rt<<1|1] = (mul[rt<<1|1]*mul[rt])%p; 31 add[rt<<1] = (add[rt<<1]*mul[rt]+add[rt])%p; 32 add[rt<<1|1] = (add[rt<<1|1]*mul[rt]+add[rt])%p; 33 mul[rt] = 1;add[rt] = 0; 34 } 35 void build(int l,int r,int rt) { 36 mul[rt] = 1,add[rt] = 0; 37 if (l==r) { 38 sum[rt] = read();return ; 39 } 40 int m = (l + r) / 2; 41 build(lson); 42 build(rson); 43 pushup(rt); 44 } 45 void update(int l,int r,int rt,int L,int R,int x,int tp) { 46 if (L <= l && r <= R) { 47 if (tp==0) add[rt] = (add[rt]+x)%p,sum[rt] = (sum[rt]+(r-l+1)*x)%p; 48 else mul[rt]=(mul[rt]*x)%p,add[rt]=(add[rt]*x)%p,sum[rt]=(sum[rt]*x)%p; 49 return ; 50 } 51 pushdown(rt,r-l+1); 52 int m = (l + r) / 2; 53 if (L <= m) update(lson,L,R,x,tp); 54 if (R > m) update(rson,L,R,x,tp); 55 pushup(rt); 56 } 57 LL query(int l,int r,int rt,int L,int R) { 58 if (L <= l && r <= R) { 59 return sum[rt] % p; 60 } 61 pushdown(rt,r-l+1); 62 int m = (l + r) / 2; 63 LL ret = 0; 64 if (L <= m) ret = (ret + query(lson,L,R)) % p; 65 if (R > m) ret = (ret + query(rson,L,R)) % p; 66 return ret % p; 67 } 68 int main () { 69 n = read(),m = read(),p = read(); 70 build(1,n,1); 71 while (m--) { 72 int opt = read(); 73 if (opt==1) { 74 int a = read(),b = read(),c = read(); 75 update(1,n,1,a,b,c,1); 76 } else if (opt==2) { 77 int a = read(),b = read(),c = read(); 78 update(1,n,1,a,b,c,0); 79 } else { 80 int a = read(),b = read(); 81 printf("%lld\n",(query(1,n,1,a,b) + p)%p); 82 } 83 } 84 return 0; 85 }