Topic links: https://www.luogu.org/problem/P3373
Talk about priority issues:
1. The order of addition and multiplication are not the same can lead to different results
For example: (A + B) C is not equal to A C B +
And when the record mark of lazy, addition and multiplication both markers put together, do not know what the first, after which.
So to determine a priority
We analyze both orders:
(1) after the first addition and multiplication: (A + B) C A = C + B * C
(2) after the first multiply-add: a * c + b
Compare, we found that after the first addition and multiplication is equivalent to the above the following equation, in addition above a multi-ride c
So long as we are after the first addition and multiplication formula, as long as adding a * c can be converted for the first multiply equation
Specifically multiplication operation is added when the mark, the mark adding enough * c
So, we set out a general order: first multiply-add
Then when marking the transfer pushdown, the son of addition flag must maintain complete transfer order first by the addition of
For example: A c + b This is a lazy son of the original mark and then adding C and B are labeled lazy father, then in accordance with the first multiply so should be considered: (A c + b) * C + B
Simplification: A = C C + B C + B *
= a(cC) + (b*C+B)
Therefore, after laminating a lazy original tag should be such that the multiplication tag is C C, the addition is labeled B C + B
1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <stdbool.h> 5 #include <stdlib.h> 6 #include <string> 7 #include <string.h> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <math.h> 13 14 #define INF 0x3f3f3f3f 15 #define LL long long 16 using namespace std; 17 18 const int maxn = 300100; 19 LL arr[maxn]; 20 LL p; 21 22 struct segment_tree{ 23 int l,r; 24 LL val; 25 LL mul,add; 26 }tree[maxn*4]; 27 28 void pushup(int nod){ 29 tree[nod].val = (tree[nod<<1].val + tree[(nod<<1)+1].val) % p; 30 } 31 32 void pushdown(int nod){ 33 int l = tree[nod].l,r = tree[nod].r; 34 int mid = (l + r) >> 1; 35 // 我们假设的是乘法优先 36 tree[nod<<1].val = (tree[nod<<1].val*tree[nod].mul + tree[nod].add*(mid-l+1)) % p; 37 tree[(nod<<1)+1].val = (tree[(nod<<1)+1].val*tree[nod].mul + tree[nod].add*(r-mid)) % p; 38 // 维护 mul 和 add 39 tree[nod<<1].mul = (tree[nod<<1].mul*tree[nod].mul) % p; 40 tree[(nod<<1)+1].mul = (tree[(nod<<1)+1].mul*tree[nod].mul) % p; 41 tree[nod<<1].add = (tree[nod<<1].add*tree[nod].mul+tree[nod].add) % p; 42 tree[(nod<<1)+1].add = (tree[(nod<<1)+1].add*tree[nod].mul+tree[nod].add) % p; 43 // 注意清空 44 tree[nod].mul = 1; 45 tree[nod].add = 0; 46 } 47 48 void build(int l,int r,int nod){ 49 tree[nod].mul = 1; 50 tree[nod].add = 0; 51 tree[nod].l = l; 52 tree[nod].r = r; 53 if (l == r){ 54 tree[nod].val = arr[l] % p; 55 return ; 56 } 57 int mid = (l + r) >> 1; 58 build(l,mid,nod<<1); 59 build(mid+1,r,(nod<<1)+1); 60 pushup(nod); 61 } 62 void updata1(int x,int y,LL k,int nod=1){ // 乘法 63 int l = tree[nod].l,r = tree[nod].r; 64 if (x <= l && y >= r){ 65 tree[nod].val = (tree[nod].val * k) % p; 66 Tree [NOD] .mul = (Tree [NOD] .mul * k)% the p-; 67 // Here is what we said adding multiplication mark the time that the addition flag like a * c 68 Tree [NOD] .add = (Tree [NOD] .add * K)% P; 69 return ; 70 } 71 is pushdown (NOD); 72 int MID = (L + R & lt) >> . 1 ; 73 is IF (X <= MID) { 74 updata1 ( X, Y, K, NOD << . 1 ); 75 } 76 IF (Y> MID) { 77 updata1 (X, Y, K, (NOD << . 1 ) + . 1 ); 78 } 79 pushup(nod); 80 } 81 82 void updata2(int x,int y,LL k,int nod=1){ // 加法 83 int l = tree[nod].l,r = tree[nod].r; 84 if (x <= l && y >= r){ 85 tree[nod].add = (tree[nod].add + k) % p; 86 tree[nod].val = (tree[nod].val + (r-l+1) * k) % p; 87 return ; 88 } 89 pushdown(nod); 90 int mid = (l + r) >> 1; 91 if (x <= mid){ 92 updata2(x,y,k,nod<<1); 93 } 94 if (y > mid){ 95 updata2(x,y,k,(nod<<1)+1); 96 } 97 pushup(nod); 98 } 99 100 LL query(int x,int y,int nod=1){ 101 int l = tree[nod].l,r = tree[nod].r; 102 if (x <= l && y >= r){ 103 return tree[nod].val % p; 104 } 105 pushdown(nod); 106 int mid = (l + r) >> 1; 107 LL sum = 0; 108 if (x <= mid){ 109 sum += query(x,y,nod<<1); 110 } 111 if (y > mid){ 112 sum += query(x,y,(nod<<1)+1); 113 } 114 return sum % p; 115 } 116 117 int main(){ 118 int n,m; 119 scanf("%d%d%lld",&n,&m,&p); 120 for (int i=1;i<=n;i++){ 121 scanf("%lld",&arr[i]); 122 } 123 build(1,n,1); 124 while (m--){ 125 int op; 126 scanf("%d",&op); 127 int x,y; 128 LL k; 129 if (op == 1){ 130 scanf("%d%d%lld",&x,&y,&k); 131 updata1(x,y,k); 132 } 133 else if (op == 2){ 134 scanf("%d%d%lld",&x,&y,&k); 135 updata2(x,y,k); 136 } 137 else { 138 scanf("%d%d",&x,&y); 139 printf("%lld\n",query(x,y)); 140 } 141 } 142 return 0; 143 }