Luogu 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
1 //2018年2月22日21:51:08 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 int n, m, mo; 9 int A[410000], B[410000], sum[410000], size[410000]; 10 11 void change(int k1){ 12 sum[k1] = (sum[k1*2]+sum[k1*2+1]) % mo; 13 } 14 15 void buildtree(int k1, int l, int r){ 16 size[k1] = r-l+1; B[k1] = 1; 17 if(l == r){ 18 scanf("%d", &sum[k1]); return; 19 } 20 int mid = (l+r) >> 1; 21 buildtree(k1*2, l, mid); 22 buildtree(k1*2+1, mid+1, r); 23 change(k1); 24 } 25 26 void add(int k1, int x){ 27 A[k1] = (A[k1]+x) % mo; 28 sum[k1] = (sum[k1]+1ll*size[k1]*x) % mo; 29 } 30 31 void chen(int k1, int x){ 32 A[k1] = 1ll*A[k1]*x % mo; 33 B[k1] = 1ll*B[k1]*x % mo; 34 sum[k1] = 1ll * sum[k1]*x % mo; 35 } 36 37 void pushdown(int k1){ 38 if(B[k1] != 1){ 39 chen(k1*2, B[k1]); 40 chen(k1*2+1, B[k1]); B[k1] = 1; 41 } 42 if(A[k1]){ 43 add(k1*2, A[k1]); 44 add(k1*2+1, A[k1]); 45 A[k1] = 0; 46 } 47 } 48 49 void add(int k1, int l, int r, int L, int R, int x){ 50 if(l>R || r<L) return; 51 if(l>=L && r<=R){ 52 add(k1, x); 53 return; 54 } 55 int mid = (l+r) >> 1; 56 pushdown(k1); 57 add(k1*2, l, mid, L, R, x); 58 add(k1*2+1, mid+1, r, L, R, x); 59 change(k1); 60 } 61 62 void chen(int k1, int l, int r, int L, int R, int x){ 63 if(l>R || r<L) return; 64 if(l>=L && r<=R){ 65 chen(k1, x); return; 66 } 67 int mid = l+r >> 1; 68 pushdown(k1); 69 chen(k1*2, l, mid, L, R, x); 70 chen(k1*2+1, mid+1, r, L, R, x); 71 change(k1); 72 } 73 74 int find(int k1, int l, int r, int L, int R){ 75 if(l>R || r<L) return 0; 76 if(l>=L && r<=R) return sum[k1]; 77 int mid = l+r >> 1; 78 pushdown(k1); 79 return (find(k1*2,l,mid,L,R) + find(k1*2+1,mid+1,r,L,R) ) % mo; 80 } 81 82 int main(){ 83 scanf("%d%d%d", &n, &m, &mo); 84 buildtree(1, 1, n); 85 for(; m; m--){ 86 int k1, k2, k3; 87 scanf("%d%d%d", &k1, &k2, &k3); 88 if(k1 == 2){ 89 int k4; scanf("%d", &k4); add(1, 1, n, k2, k3, k4); 90 }else if(k1 == 1){ 91 int k4; scanf("%d", &k4); chen(1, 1, n, k2, k3, k4); 92 }else printf("%d\n", find(1, 1, n, k2, k3)); 93 } 94 95 return 0; 96 }