#include <bits/stdc++.h>
using
namespace
std;
typedef
struct
node {
int
sum;
int
mx1;
int
mx2;
int
cnt_mx1;
int
cnt_mx2;
node()
{
sum = mx1 = mx2 = 0;
cnt_mx1 = cnt_mx2 = 0;
}
} node;
const
int
N = 1e5 + 5;
node tree[N];
int
lazy[N];
void
combine(
int
pos)
{
map<
int
,
int
> x;
x[tree[2 * pos + 1].mx1] += tree[2 * pos + 1].cnt_mx1;
x[tree[2 * pos + 1].mx2] += tree[2 * pos + 1].cnt_mx2;
x[tree[2 * pos + 2].mx1] += tree[2 * pos + 2].cnt_mx1;
x[tree[2 * pos + 2].mx2] += tree[2 * pos + 2].cnt_mx2;
vector<pair<
int
,
int
> > v;
for
(
auto
it = x.begin(); it != x.end(); it++) {
v.push_back({ it->first, it->second });
}
int
n = v.size();
tree[pos].mx1 = v[n - 1].first;
tree[pos].cnt_mx1 = v[n - 1].second;
if
(n == 1) {
tree[pos].mx2 = tree[pos].cnt_mx2 = 0;
}
else
{
tree[pos].mx2 = v[n - 2].first;
tree[pos].cnt_mx2 = v[n - 2].second;
}
tree[pos].sum = tree[2 * pos + 1].sum
+ tree[2 * pos + 2].sum;
}
bool
tag_condition(
int
pos,
int
x)
{
if
(tree[pos].mx1 > x
&& tree[pos].mx2 <= x) {
return
true
;
}
return
false
;
}
void
pushdown(
int
beg,
int
end,
int
pos)
{
if
(tag_condition(pos, lazy[pos])) {
int
initsum = tree[pos].mx1 * tree[pos].cnt_mx1;
int
finsum = lazy[pos] * tree[pos].cnt_mx1;
tree[pos].sum += finsum - initsum;
if
(beg == end)
tree[pos].mx1 = lazy[pos];
else
{
if
(lazy[pos] > tree[pos].mx2)
tree[pos].mx1 = lazy[pos];
else
{
tree[pos].mx1 = lazy[pos];
tree[pos].cnt_mx1 += tree[pos].cnt_mx2;
tree[pos].mx2 = tree[pos].cnt_mx2 = 0;
map<
int
,
int
> x;
x[tree[2 * pos + 1].mx1] += tree[2 * pos + 1].cnt_mx1;
x[tree[2 * pos + 1].mx2] += tree[2 * pos + 1].cnt_mx2;
x[tree[2 * pos + 2].mx1] += tree[2 * pos + 2].cnt_mx1;
x[tree[2 * pos + 2].mx2] += tree[2 * pos + 2].cnt_mx2;
for
(
auto
it = x.begin(); it != x.end(); it++) {
if
(it->first != tree[pos].mx1
&& it->first > tree[pos].mx2) {
tree[pos].mx2 = it->first;
tree[pos].cnt_mx2 = it->second;
}
}
}
lazy[2 * pos + 1] = min(lazy[2 * pos + 1],
lazy[pos]);
lazy[2 * pos + 2] = min(lazy[2 * pos + 2],
lazy[pos]);
}
}
lazy[pos] = INT_MAX;
}
void
update(
int
beg,
int
end,
int
l,
int
r,
int
pos,
int
val)
{
if
(lazy[pos] < INT_MAX)
pushdown(beg, end, pos);
if
(l <= beg and r >= end
&& tag_condition(pos, val)) {
lazy[pos] = min(lazy[pos], val);
pushdown(beg, end, pos);
return
;
}
else
if
(l > end || r < beg
|| beg > end
|| tree[pos].mx1 <= val) {
return
;
}
else
{
int
mid = (beg + end) / 2;
update(beg, mid, l, r,
2 * pos + 1, val);
update(mid + 1, end, l, r,
2 * pos + 2, val);
combine(pos);
}
}
int
query1(
int
beg,
int
end,
int
l,
int
r,
int
pos)
{
if
(lazy[pos] < INT_MAX) {
pushdown(beg, end, pos);
}
if
(l <= beg && r >= end) {
return
tree[pos].mx1;
}
else
if
(l > end || r < beg
|| beg > end) {
return
0;
}
else
{
int
mid = (beg + end) / 2;
return
max(query1(beg, mid, l, r,
2 * pos + 1),
query1(mid + 1, end, l,
r, 2 * pos + 2));
}
}
int
query2(
int
beg,
int
end,
int
l,
int
r,
int
pos)
{
if
(lazy[pos] < INT_MAX)
pushdown(beg, end, pos);
if
(l <= beg and r >= end)
return
tree[pos].sum;
else
if
(l > end || r < beg
|| beg > end) {
return
0;
}
else
{
int
mid = (beg + end) / 2;
return
query2(beg, mid, l, r,
2 * pos + 1)
+ query1(mid + 1, end, l,
r, 2 * pos + 2);
}
}
void
constr(
int
arr[],
int
beg,
int
end,
int
pos)
{
if
(beg == end) {
int
x = arr[beg];
tree[pos].sum = x;
tree[pos].mx1 = x;
tree[pos].cnt_mx1 = 1;
tree[pos].mx2 = 0;
tree[pos].cnt_mx2 = 0;
return
;
}
else
{
int
mid = (beg + end) / 2;
constr(arr, beg, mid, 2 * pos + 1);
constr(arr, mid + 1, end, 2 * pos + 2);
combine(pos);
}
}
void
construct(
int
arr[],
int
n)
{
for
(
int
i = 0; i < N; i++) {
lazy[i] = INT_MAX;
}
constr(arr, 0, n - 1, 0);
}
int
main()
{
int
arr[] = { 1, 2, 3, 4, 5 };
construct(arr, 5);
cout << "Maximum in [2, 4] before update: ";
cout << query1(0, 4, 2, 4, 0) << endl;
cout << "Sum in [2, 4] before update: ";
cout << query2(0, 4, 2, 4, 0) << endl;
update(0, 4, 2, 5, 0, 3);
cout << endl;
cout << "Updated array elements between "
<< "[2, 4] as min(arr[i], 3)" << endl;
cout << endl;
cout << "Maximum in [2, 4] after update: ";
cout << query1(0, 4, 2, 4, 0) << endl;
cout << "Sum in [2, 4] after update: ";
cout << query2(0, 4, 2, 4, 0) << endl;
return
0;
}