题目描述
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
输入
第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
输出
对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
样例输入
7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7
样例输出
2
35
题解
线段树裸题
唯一要注意的是两种标记的处理:pushdown中始终是先乘后加,而在乘的时候把原有的加标记也乘上这个数。原理应该不难想。
1 #include <cstdio> 2 #include <cstring> 3 #define lson l , mid , x << 1 4 #define rson mid + 1 , r , x << 1 | 1 5 typedef long long lint; 6 lint mod , sum[400010] , add[400010] , mul[400010]; 7 void pushup(int x) 8 { 9 sum[x] = (sum[x << 1] + sum[x << 1 | 1]) % mod; 10 } 11 void pushdown(int l , int r , int x) 12 { 13 int mid = (l + r) >> 1; 14 if(mul[x] != 1) 15 { 16 sum[x << 1] = sum[x << 1] * mul[x] % mod; 17 sum[x << 1 | 1] = sum[x << 1 | 1] * mul[x] % mod; 18 add[x << 1] = add[x << 1] * mul[x] % mod; 19 add[x << 1 | 1] = add[x << 1 | 1] * mul[x] % mod; 20 mul[x << 1] = mul[x << 1] * mul[x] % mod; 21 mul[x << 1 | 1] = mul[x << 1 | 1] * mul[x] % mod; 22 mul[x] = 1; 23 } 24 if(add[x]) 25 { 26 sum[x << 1] = (sum[x << 1] + add[x] * (mid - l + 1)) % mod; 27 sum[x << 1 | 1] = (sum[x << 1 | 1] + add[x] * (r - mid)) % mod; 28 add[x << 1] = (add[x << 1] + add[x]) % mod; 29 add[x << 1 | 1] = (add[x << 1 | 1] + add[x]) % mod; 30 add[x] = 0; 31 } 32 } 33 void build(int l , int r , int x) 34 { 35 mul[x] = 1; 36 if(l == r) 37 { 38 scanf("%lld" , &sum[x]); 39 sum[x] %= mod; 40 return; 41 } 42 int mid = (l + r) >> 1; 43 build(lson); 44 build(rson); 45 pushup(x); 46 } 47 void updatemul(int b , int e , lint m , int l , int r , int x) 48 { 49 if(b <= l && r <= e) 50 { 51 sum[x] = sum[x] * m % mod; 52 add[x] = add[x] * m % mod; 53 mul[x] = mul[x] * m % mod; 54 return; 55 } 56 pushdown(l , r , x); 57 int mid = (l + r) >> 1; 58 if(b <= mid) updatemul(b , e , m , lson); 59 if(e > mid) updatemul(b , e , m , rson); 60 pushup(x); 61 } 62 void updateadd(int b , int e , lint a , int l , int r , int x) 63 { 64 if(b <= l && r <= e) 65 { 66 sum[x] = (sum[x] + a * (r - l + 1)) % mod; 67 add[x] = (add[x] + a) % mod; 68 return; 69 } 70 pushdown(l , r , x); 71 int mid = (l + r) >> 1; 72 if(b <= mid) updateadd(b , e , a , lson); 73 if(e > mid) updateadd(b , e , a , rson); 74 pushup(x); 75 } 76 lint query(int b , int e , int l , int r , int x) 77 { 78 if(b <= l && r <= e) 79 return sum[x]; 80 pushdown(l , r , x); 81 int mid = (l + r) >> 1; 82 lint ans = 0; 83 if(b <= mid) ans = (ans + query(b , e , lson)) % mod; 84 if(e > mid) ans = (ans + query(b , e , rson)) % mod; 85 return ans; 86 } 87 int main() 88 { 89 int n , m , p , l , r; 90 lint k; 91 scanf("%d%lld" , &n , &mod); 92 build(1 , n , 1); 93 scanf("%d" , &m); 94 while(m -- ) 95 { 96 scanf("%d%d%d" , &p , &l , &r); 97 switch(p) 98 { 99 case 1: scanf("%lld" , &k); updatemul(l , r , k , 1 , n , 1); break; 100 case 2: scanf("%lld" , &k); updateadd(l , r , k , 1 , n , 1); break; 101 default: printf("%lld\n" , query(l , r , 1 , n , 1)); 102 } 103 } 104 return 0; 105 }
【bzoj1798】[Ahoi2009]Seq 维护序列seq
原文:http://www.cnblogs.com/GXZlegend/p/6406433.html