区间最值操作
给定一个长度为 N序列,编号从1 到 N。要求支持下面几种操作:
1.给一个区间[L,R] 加上一个数x
2.把一个区间[L,R] 里小于x 的数变成x
3.把一个区间[L,R] 里大于x 的数变成x
4.求区间[L,R] 的和
5.求区间[L,R] 的最大值
6.求区间[L,R] 的最小值
#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
template<class...Args>
void debug(Args... args) {
//Parameter pack
auto tmp = {
(cout << args << ' ', 0)... };
cout << "\n";
}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
const ll N = 1e6 + 5;
const ll MOD = 998244353;
const ll INF = 1e9 + 7;
struct node {
int maxv, next_max, cnt_max;//最大值 次大值 最大值个数
int minv, next_min, cnt_min;//最小值 次小值 最小值个数
int add;//加法懒标记
ll sum;//区间和
}tree[N << 2];
int w[N];
void push_up(int root) {
//更新和
tree[root].sum = tree[root << 1].sum + tree[root << 1 | 1].sum;
//更新最大值及其附加属性
if (tree[root << 1].maxv == tree[root << 1 | 1].maxv) {
//如果左子树的最大值等于右子树的最大值
tree[root].maxv = tree[root << 1].maxv;//将根节点的最大值更新
tree[root].cnt_max = tree[root << 1].cnt_max + tree[root << 1 | 1].cnt_max;//根节点最大值的数量为左右子树最大值的个数和
tree[root].next_max = max(tree[root << 1].next_max, tree[root << 1 | 1].next_max);//根节点的次大值为左右子树次大值的最大的那个
}
else if (tree[root << 1].maxv > tree[root << 1 | 1].maxv) {
//如果左子树的最大值大于右子树的最大值
tree[root].maxv = tree[root << 1].maxv;//根节点的最大值左子树的最大值
tree[root].cnt_max = tree[root << 1].cnt_max;//根节点的最大值数量为左子树最大值的数量
tree[root].next_max = max(tree[root << 1].next_max, tree[root << 1 | 1].maxv);//根节点的次大值为左子树次大值和右子树最大值的较大者
}
else {
//如果右子树的最大值大于左子树的最大值
tree[root].maxv = tree[root << 1 | 1].maxv;
tree[root].cnt_max = tree[root << 1 | 1].cnt_max;
tree[root].next_max = max(tree[root << 1 | 1].next_max, tree[root << 1].maxv);
}
//更新最小值及其附加属性
if (tree[root << 1].minv == tree[root << 1 | 1].minv) {
//如果左子树的最小值等于右子树的最小值
tree[root].minv = tree[root << 1].minv;//将根节点的最大值更新