On the tree line Segment Tree

   As we all know, algo segment tree is a very important one!

  I. Introduction

    

  Segment tree is a binary search tree, and the interval tree is similar, it means a section partitioned into intervals, a leaf node corresponding to each unit section of the segment tree.

  Using the segment tree can quickly find a particular node number appearing in a number of line segments, the time complexity of O (logN). Without the optimization of space complexity 2N, 4N in general but also to open an array of practical applications in order to avoid cross-border, and therefore sometimes necessary to make discrete space compression.

   II. Use

  A single point: Query (query) to modify (add, mul)

    Interval: query (and section), modifying the maximum value (max), the minimum value (min) .

  

  III. Implementation

  1. achievements

   Since each point represents a range, so he has a lot of information (son left, right, son, interval sum) so we keep the structure because then use to mark lazy, so lazy structure there are two markers.

  Lazy tag    : FIG above example, if you want to 1 - Add a 6 interval, we will pass this information from the root node to the next layer, then add = 2,3 point has a lazy marker 1, so it is said that it has added more than 1, the next time you have to add, then applied directly to the lazy mark. For example, you would earn a sum of money, temporarily do not, there is a bank. If, after solving recursively, then the lazy pass mark on down, and they have to pass after clearing! State (so that the original state is updated subinterval points + the number of pass-ri * lazy marker, (example sum = 5 (its original state) + 4 (the number of section 4, there are added a 2 ) * 2 (labeled lazy)) is metaphysical -------

  Multiplication lazy mark (luogu p3373): requires special attention under

    For example, originally labeled as lazy 2 + 3
  now pass to the next by 8 then becomes (2 + 3) * 8
  and then send it a plus three, will become a (2 + 3 + 3) * 8
  So we keep so 2 * 8 + 3 * 8
  so after 3 plus value is correct!

  The Code

 

% P code is a subject of the request

 1 struct Node {
 2     int l, r;
 3     ll sum;
 4     ll add, mul;
 5     
 6     Node() {
 7         l = r = sum = add = 0;
 8         mul = 1;
 9     }
10     
11     void update_add(ll value) {
12         add = (add + value) % P;
13         sum = (sum + (r - l + 1) * value) % P;
14     }
15     
16     void update_mul(ll value) {
17         sum = (sum * value) % P;
18         mul = (mul * value) % P;
19         add = (add * value) % P;
20     }
21 } t[N << 2];

My contribution may be more strange, when recursion to root again cin, while recursively while updating (push_up, behind)

 1 void build_tree(int p, int l, int r) {
 2     t[p].l = l, t[p].r = r;
 3     if (l == r) {
 4         cin >> t[p].sum;
 5         return;
 6     }
 7     int mid = (t[p].l + t[p].r) >> 1;
 8     build_tree(lc(p), l, mid);
 9     build_tree(rc(p), mid + 1, r);
10     push_up(p); 
11 }

Son son left and right

inline int lc(int p) {
    return p << 1;
}

inline int rc(int p) {
    return p << 1 | 1;
}

Up push_up update information (sum), down lazy pass mark (push_down)  Remember to pass their own state to be restored after Oh!

 1 void push_up(int p) {
 2     t[p].sum = t[lc(p)].sum + t[rc(p)].sum;
 3 }
 4 
 5 void push_down(int p) {
 6     if (t[p].mul != 1) {
 7         t[lc(p)].update_mul(t[p].mul);
 8         t[rc(p)].update_mul(t[p].mul);
 9         t[p].mul = 1; 
10     }
11     if (t[p].add) {
12         t[lc(p)].update_add(t[p].add);
13         t[rc(p)].update_add(t[p].add);
14         t[p].add = 0;
15     }
16 }

Å%%%Then

When we change the interval

(Black is the total range, red for the need to amend section)

If the current range is a subset of the entire section of the ---- that's fine, you can directly modify

If the current range and total range intersect, then recursively, to find the first fully contained his range, and then modify, and then recursively go up

 

The Code! ! !

 

 1 void update1(int p, int l, int r, ll value) {//乘法更新
 2     if (t[p].l >= l && t[p].r <= r) {
 3         t[p].update_mul(value);
 4         return;
 5     }
 6     push_down(p);
 7     int mid = (t[p].l + t[p].r) >> 1;
 8     if (l <= mid) update1(lc(p), l, r, value);
 9     if (r > mid) update1(rc(p), l, r, value);
10     push_up(p);
11 }
12 
13 void update2(int p, int l, int r, ll value) {//加法更新
14     if (t[p].l >= l && t[p].r <= r) {
15         t[p].update_add(value);
16         return;
17     }
18     push_down(p);
19     int mid = (t[p].l + t[p].r) >> 1;
20     if (l <= mid) update2(lc(p), l, r, value);
21     if (r > mid) update2(rc(p), l, r, value);
22     push_up(p);
23 }
24 
25 ll query(int p, int l, int r) {//区间查询,如果是单点差距的话l == r
26     if (t[p].l >= l && t[p].r <= r) {
27         return t[p].sum % P;
28     }
29     push_down(p);
30     ll sum = 0;
31     int mid = (t[p].l + t[p].r) >> 1;
32     if (l <= mid) sum = (sum + query(lc(p), l, r)) % P;
33     if (r > mid) sum = (sum + query(rc(p), l, r)) % P;
34     return sum % P;
35 }

 

当然还可以求RMQ问题

 1 struct Node
 2 {
 3     ll minn,maxx;
 4 }t[];
 5 
 6 //build 里加几句
 7 t[p].maxx = max(t[lc(p)].maxx,t[rp(p)].maxx);
 8 t[p].minn = min(t[lc(p)].minn,t[rp(p)].minn);
 9 
10 
11 int ans1,ans2;
12 void new_query(int p,int l,int r)
13 {
14     if(t[p].l == l && t[p].r == r)
15     {
16         ans1 = max(ans1,t[p].maxx);
17         ans2 = max(ans2,t[p].minn);
18         return;
19     } 
20     int mid = (t[p].l + t[p].r) >> 1;
21     if(r <= mid)
22         query(lc(p),l,r);
23     else if (l > mid)
24         query(rc(p),l,r);
25     else 
26     {
27         query(lc(p),l,mid);
28         query(rp(p),mid + 1,r);
29     }
30 }

下面附上总代码(代码按照luogu 线段树2的模板打的,可AC)

 

  1 #include <iostream>
  2 #include<algorithm>
  3 using namespace std;
  4 const int N = 1e5 + 7;
  5 typedef long long ll;
  6 
  7 ll P;
  8 
  9 struct Node {
 10     int l, r;
 11     ll sum;
 12     ll add, mul;
 13 //    ll minn,mmax;
 14     Node() {
 15         l = r = sum = add = 0;
 16         mul = 1;
 17     }
 18     
 19     void update_add(ll value) {
 20         add = (add + value) % P;
 21         sum = (sum + (r - l + 1) * value) % P;
 22     }
 23     
 24     void update_mul(ll value) {
 25         sum = (sum * value) % P;
 26         mul = (mul * value) % P;
 27         add = (add * value) % P;
 28     }
 29 } t[N << 2];
 30 
 31 inline int lc(int p) {
 32     return p << 1;
 33 }
 34 
 35 inline int rc(int p) {
 36     return p << 1 | 1;
 37 }
 38 
 39 void push_up(int p) {
 40     t[p].sum = t[lc(p)].sum + t[rc(p)].sum;
 41 }
 42 
 43 void push_down(int p) {
 44     if (t[p].mul != 1) {
 45         t[lc(p)].update_mul(t[p].mul);
 46         t[rc(p)].update_mul(t[p].mul);
 47         t[p].mul = 1; 
 48     }
 49     if (t[p].add) {
 50         t[lc(p)].update_add(t[p].add);
 51         t[rc(p)].update_add(t[p].add);
 52         t[p].add = 0;
 53     }
 54 }
 55 
 56 void build_tree(int p, int l, int r) {
 57     t[p].l = l, t[p].r = r;
 58     if (l == r) {
 59         cin >> t[p].sum;
 60         return;
 61     }
 62     int mid = (t[p].l + t[p].r) >> 1;
 63     build_tree(lc(p), l, mid);
 64     build_tree(rc(p), mid + 1, r);
 65 //    t[p].maxx = max(t[lc(p)].maxx,t[rp(p)].maxx);
 66 //    t[p].minn = min(t[lc(p)].minn,t[rp(p)].minn);
 67     push_up(p); 
 68 }
 69 
 70 void update1(int p, int l, int r, ll value) {
 71     if (t[p].l >= l && t[p].r <= r) {
 72         t[p].update_mul(value);
 73         return;
 74     }
 75     push_down(p);
 76     int mid = (t[p].l + t[p].r) >> 1;
 77     if (l <= mid) update1(lc(p), l, r, value);
 78     if (r > mid) update1(rc(p), l, r, value);
 79     push_up(p);
 80 }
 81 
 82 void update2(int p, int l, int r, ll value) {
 83     if (t[p].l >= l && t[p].r <= r) {
 84         t[p].update_add(value);
 85         return;
 86     }
 87     push_down(p);
 88     int mid = (t[p].l + t[p].r) >> 1;
 89     if (l <= mid) update2(lc(p), l, r, value);
 90     if (r > mid) update2(rc(p), l, r, value);
 91     push_up(p);
 92 }
 93 
 94 ll query(int p, int l, int r) {
 95     if (t[p].l >= l && t[p].r <= r) {
 96         return t[p].sum % P;
 97     }
 98     push_down(p);
 99     ll sum = 0;
100     int mid = (t[p].l + t[p].r) >> 1;
101     if (l <= mid) sum = (sum + query(lc(p), l, r)) % P;
102     if (r > mid) sum = (sum + query(rc(p), l, r)) % P;
103     return sum % P;
104 }
105 /*int ans1,ans2;
106 void new_query(int p,int l,int r)
107 {
108     if(t[p].l == l && t[p].r == r)
109     {
110         ans1 = max(ans1,t[p].maxx);
111         ans2 = max(ans2,t[p].minn);
112         return;
113     } 
114     int mid = (t[p].l + t[p].r) >> 1;
115     if(r <= mid)
116         new_query(lc(p),l,r);
117     else if (l > mid)
118         new_query(rc(p),l,r);
119     else 
120     {
121         new_query(lc(p),l,mid);
122         new_query(rp(p),mid + 1,r);
123     }
124 }
125 */
126 
127 int main()
128 {
129     int n, m;
130     cin >> n >> m >> P;
131     build_tree(1, 1, n);
132     while (m--) {
133         int op, l, r, num;
134         cin >> op >> l >> r;
135         if (op == 1 || op == 2) cin >> num;
136         if (op == 1) update1(1, l, r, num);
137         else if (op == 2) update2(1, l, r, num);
138         else cout << query(1, l, r) << endl; 
139     }
140 }
141 
142 //Juddav007 0.0
View Code(all)

 

THANKS FOR WATCHING!

 

Guess you like

Origin www.cnblogs.com/juddav007/p/11748956.html