-
Notifications
You must be signed in to change notification settings - Fork 0
/
lazypropagation.cpp
138 lines (128 loc) · 3.69 KB
/
lazypropagation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* In this code we have a very large array called arr, and very large set of operations
* Operation #1: Increment the elements within range [i, j] with value val
* Operation #2: Get max element within range [i, j]
* Build tree: build_tree(1, 0, N-1)
* Update tree: update_tree(1, 0, N-1, i, j, value)
* Query tree: query_tree(1, 0, N-1, i, j)
*/
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 10;
int A[MAXN];
int tree[4 * MAXN]; // 4 * size of array would suffic as the size of segment tree.
/**
**
**
** Builds segment tree in O(number of nodes)
** number of nodes are approximated by 4 * N
**
** segL is left boundary of segment stored in the node
** segR is right boundary of segment stored in the node
**
**
***/
void build_tree(int node,int segL,int segR){
if( segL > segR) return ;
if(segL == segR){ //leaf node
tree[node] = A[segL];
return;
}
int mid=(segL + segR) / 2;
int leftNode = 2 * node;
int rightNode = 2 * node + 1;
build_tree(leftNode, segL, mid);
build_tree(rightNode, mid + 1, segR);
tree[node] = max(tree[leftNode], tree[rightNode]);
}
void relax(int node){
if(lazy[node] != 0){
//passing on laziness to children
tree[node] += lazy[node];
if(a != b){
lazy[2 * node] += lazy[node];
lazy[2 * node + 1] += lazy[node];
}
lazy[node]=0;
}
}
/**
**
**
** updates segment tree
**
** segL is left boundary of segment stored in the node
** segR is right boundary of segment stored in the node
**
** ql is the left boundary of query range
** qr is the right boundary of query range
**
** `value` is the value to be added in range [ql..qr]
**
***/
void update_tree(int node, int segL, int segR, int ql, int qr, int value){
if(segL > segR || segL > qr || segR < ql) return; //range out of segment range
relax(node);
if(ql <= segL && segR <= qr){
tree[node] += value;
if(segL != segR){
lazy[2 * node] += value;
lazy[2 * node + 1] += value;
}
return;
}
int mid=(segL + segR) / 2;
int leftNode = 2 * node;
int rightNode = 2 * node + 1;
update_tree(leftNode, segL, mid, ql, qr, value);
update_tree(rightNode, mid + 1, segR, ql, qr, value);
tree[node] = max(tree[leftNode], tree[rightNode]);
}
/**
**
**
** queries segment tree
**
** segL is left boundary of segment stored in the node
** segR is right boundary of segment stored in the node
**
** ql is the left boundary of query range
** qr is the right boundary of query range
**
**
***/
int query_tree(int node, int segL, int segR, int ql, int qr) {
if(segL > segR || segL > qr || segR < ql) return -INF; //out of the range
relax(node);
if(ql <= segL && qr >= segR) return tree[node]; // segment range entirely in the query.
int mid=(segL + segR) / 2;
int leftNode = 2 * node;
int rightNode = 2 * node + 1;
return max(query_tree(leftNode, segL, mid, ql, qr), query_tree(rightNode, mid + 1, segR, ql, qr));
}
int main(){
int N, Q; cin >> N >> Q;
for(int i = 0;i < N;i++){
cin >> A[i];
}
//build the tree
build_tree(1, 0, N - 1);
for(int i = 0;i < Q;i++){
int type, l, r, k;
cin >> type;
switch(type){
case 1:
//query to add k in range [l..r]
cin >> l >> r >> k;
update_tree(1, 0, N - 1, l, r, k);
break;
case 2:
//query to print max of range [l..r]
cin >> l >> r;
cout << query_tree(1, 0, N - 1, l, r) << "\n";
break;
}
}
return 0;
}