P3373 template [2] segment tree (tree line mark multiple entry)

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 }

 

Guess you like

Origin www.cnblogs.com/-Ackerman/p/11456072.html