Repository navigation
Expand file tree
/
Copy pathstd.cpp
More file actions
119 lines (119 loc) · 2.62 KB
/
Copy pathstd.cpp
File metadata and controls
119 lines (119 loc) · 2.62 KB
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
// GPT-6: explicit pop-on-equality specification, visibility segment tree, implementation.
#include <algorithm>
#include <iostream>
#include <vector>
struct FNode
{
int Maximum = -1;
int Count = 0;
};
class FTree
{
std::vector<FNode> Nodes;
int CountAbove(int Node, int Left, int Right, int Threshold) const
{
if (Nodes[Node].Maximum <= Threshold)
{
return 0;
}
if (Left == Right)
{
return 1;
}
int Middle = (Left + Right) / 2;
if (Nodes[Node * 2 + 1].Maximum <= Threshold)
{
return CountAbove(Node * 2, Left, Middle, Threshold);
}
return CountAbove(Node * 2 + 1, Middle + 1, Right, Threshold)
+ Nodes[Node].Count - Nodes[Node * 2 + 1].Count;
}
void Pull(int Node, int Left, int Right)
{
int Middle = (Left + Right) / 2;
Nodes[Node].Maximum = std::max(Nodes[Node * 2].Maximum, Nodes[Node * 2 + 1].Maximum);
Nodes[Node].Count = Nodes[Node * 2 + 1].Count
+ CountAbove(Node * 2, Left, Middle, Nodes[Node * 2 + 1].Maximum);
}
public:
explicit FTree(int n) : Nodes(4 * n)
{
}
void Build(int Node, int Left, int Right, const std::vector<int>& Values)
{
if (Left == Right)
{
Nodes[Node] = {Values[Left], 1};
return;
}
int Middle = (Left + Right) / 2;
Build(Node * 2, Left, Middle, Values);
Build(Node * 2 + 1, Middle + 1, Right, Values);
Pull(Node, Left, Right);
}
void Update(int Node, int Left, int Right, int Position, int Value)
{
if (Left == Right)
{
Nodes[Node] = {Value, 1};
return;
}
int Middle = (Left + Right) / 2;
if (Position <= Middle)
{
Update(Node * 2, Left, Middle, Position, Value);
}
else
{
Update(Node * 2 + 1, Middle + 1, Right, Position, Value);
}
Pull(Node, Left, Right);
}
int Query(int Node, int Left, int Right, int l, int r, int& Threshold) const
{
if (r < Left || Right < l)
{
return 0;
}
if (l <= Left && Right <= r)
{
int Answer = CountAbove(Node, Left, Right, Threshold);
Threshold = std::max(Threshold, Nodes[Node].Maximum);
return Answer;
}
int Middle = (Left + Right) / 2;
int Answer = Query(Node * 2 + 1, Middle + 1, Right, l, r, Threshold);
return Answer + Query(Node * 2, Left, Middle, l, r, Threshold);
}
};
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
int m;
std::cin >> n >> m;
std::vector<int> Values(n);
for (int& Value : Values)
{
std::cin >> Value;
}
FTree Tree(n);
Tree.Build(1, 0, n - 1, Values);
while (m--)
{
int Type;
int x;
int y;
std::cin >> Type >> x >> y;
if (Type == 1)
{
Tree.Update(1, 0, n - 1, x - 1, y);
}
else
{
int Threshold = -1;
std::cout << Tree.Query(1, 0, n - 1, x - 1, y - 1, Threshold) << '\n';
}
}
}