Skip to content

Commit 511494f

Browse files
Add files via upload
1 parent d142d29 commit 511494f

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
There are N numbers a[0],a[1]..a[N - 1]. Initally all are 0. You have to perform two types of operations :
2+
3+
1) Increase the numbers between indices A and B (inclusive) by 1. This is represented by the command "0 A B"
4+
2) Answer how many numbers between indices A and B (inclusive) are divisible by 3. This is represented by the command "1 A B".
5+
6+
--------------------------------------------
7+
8+
Since there are many range updates, it's clear lazy propagation must be used.
9+
10+
What happens in one operation. All n = m (mod 3), will become m + 1 (mod 3).
11+
12+
Keep track of all the remainders mod 3 in every range.
13+
14+
-------------------------------------------------------------
15+
16+
void build(int node, int start, int end)
17+
{
18+
if(start == end)
19+
{
20+
int mod = element[start]%3;
21+
int mod_2 = (mod + 1)%3, mod_3 = (mod + 2)%3;
22+
23+
tree[node][mod] = 1;
24+
tree[node][mod_2] = tree[node][mod_3] = 0;
25+
26+
return;
27+
}
28+
29+
int mid = (start + end)/2;
30+
31+
build(2*node, start, mid);
32+
build(2*node + 1, mid + 1, end);
33+
34+
for(int m = 0; m < 3; m++)
35+
tree[node][m] = tree[2*node][m] + tree[2*node + 1][m];
36+
}
37+
38+
----------------------------------------------------------------------
39+
40+
We only need to know the number of operations mod 3. Make it 0 after it has been propagated.
41+
42+
void propagate(int node, int start, int end)
43+
{
44+
int no_of_additions = lazy[node]%3;
45+
46+
if(no_of_additions == 1)
47+
{
48+
swap(tree[node][0], tree[node][1], tree[node][2]);
49+
}
50+
else if(no_of_additions == 2)
51+
{
52+
swap(tree[node][0], tree[node][2], tree[node][1]);
53+
}
54+
55+
if(start != end)
56+
{
57+
lazy[2*node] = (lazy[2*node] + lazy[node])%3;
58+
lazy[2*node + 1] = (lazy[2*node + 1] + lazy[node])%3;
59+
}
60+
lazy[node] = 0;
61+
}
62+
63+
--------------------------------------------------------------------------------------
64+
65+
For updating, first propagate the pending operations and then perform current operation.
66+
67+
void update(int node, int start, int end, int query_start, int query_end)
68+
{
69+
if(lazy[node])
70+
propagate(node, start, end);
71+
72+
if(query_start > end || query_end < start)
73+
return;
74+
75+
if(query_start <= start && end <= query_end)
76+
{
77+
swap(tree[node][0], tree[node][1], tree[node][2]);
78+
79+
if(start != end)
80+
{
81+
lazy[2*node]++;
82+
lazy[2*node] %= 3;
83+
84+
lazy[2*node + 1]++;
85+
lazy[2*node + 1] %= 3;
86+
}
87+
return;
88+
}
89+
90+
int mid = (start + end)/2;
91+
92+
update(2*node, start, mid, query_start, query_end);
93+
update(2*node + 1, mid + 1, end, query_start, query_end);
94+
95+
for(int m = 0; m < 3; m++)
96+
tree[node][m] = tree[2*node][m] + tree[2*node + 1][m];
97+
}
98+
99+
---------------------------------------------------------------------------
100+
101+
int query(int node, int start, int end, int query_start, int query_end)
102+
{
103+
if(lazy[node])
104+
propagate(node, start, end);
105+
106+
if(query_start > end || query_end < start)
107+
return 0;
108+
109+
if(query_start <= start && end <= query_end)
110+
return tree[node][0];
111+
112+
int mid = (start + end)/2;
113+
114+
int left_answer = query(2*node, start, mid, query_start, query_end);
115+
int right_answer = query(2*node + 1, mid + 1, end, query_start, query_end);
116+
117+
return (left_answer + right_answer);
118+
}

0 commit comments

Comments
 (0)