#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int n, m;
#define ls (s << 1)
#define rs (s << 1 | 1)
#define inf (int)0x3f3f3f3f3f3f3f3f
template<typename T> struct SegmentTree {
struct TreeNode { int l, r; T sum, mx, mn, add, st; } tr[N << 2];
void pushup(int s) {
tr[s].sum = tr[ls].sum + tr[rs].sum;
tr[s].mx = max(tr[ls].mx, tr[rs].mx);
tr[s].mn = min(tr[ls].mn, tr[rs].mn);
}
void pushdown(int s) {
if (tr[s].st != -inf) {
tr[s].st += tr[s].add;
tr[ls].add = tr[rs].add = 0;
tr[ls].st = tr[rs].st = tr[s].st;
tr[ls].mx = tr[rs].mx = tr[s].st;
tr[ls].mn = tr[rs].mn = tr[s].st;
tr[ls].sum = tr[s].st * (tr[ls].r - tr[ls].l + 1);
tr[rs].sum = tr[s].st * (tr[rs].r - tr[rs].l + 1);
// 向下传递后将s节点的st和add标签都清除
tr[s].st = -inf; tr[s].add = 0;
} else if (tr[s].add != 0) {
tr[ls].add += tr[s].add;
tr[rs].add += tr[s].add;
tr[ls].sum += tr[s].add * (tr[ls].r - tr[ls].l + 1);
tr[rs].sum += tr[s].add * (tr[rs].r - tr[rs].l + 1);
tr[ls].mx += tr[s].add;
tr[rs].mx += tr[s].add;
tr[ls].mn += tr[s].add;
tr[rs].mn += tr[s].add;
// 向下传递后将s节点的add标签清除
tr[s].add = 0;
}
}
void build(int l, int r, int s = 1) {
tr[s].l = l, tr[s].r = r;
tr[s].add = tr[s].sum = T(), tr[s].st = -inf, tr[s].mx = -inf, tr[s].mn = inf;
if (l == r) {
tr[s].sum = tr[s].mn = tr[s].mx = 1111; // 这里的值具体问题具体设置
return;
}
int mid = tr[s].l + tr[s].r >> 1;
if (l <= mid) build(l, mid, ls);
if (r > mid) build(mid + 1, r, rs);
pushup(s);
}
// ==================================以下都是区间操作=========================================
void update(int l, int r, T val, int s) { // 区间加法操作,即给区间每一个树都加上val
if (l <= tr[s].l && tr[s].r <= r) {
tr[s].add += val;
tr[s].mn += val;
tr[s].mx += val;
tr[s].sum += val * (tr[s].r - tr[s].l + 1);
return;
}
pushdown(s);
int mid = tr[s].l + tr[s].r >> 1;
if (l <= mid) update(l, r, val, ls);
if (r > mid) update(l, r, val, rs);
pushup(s);
}
void modify(int l, int r, T val, int s) { // 它会将指定区间 [l, r] 内的所有元素设为给定的值 val
if (l <= tr[s].l && tr[s].r <= r) {
tr[s].st = val;
tr[s].mn = tr[s].mx = val;
tr[s].sum = val * (tr[s].r - tr[s].l + 1);
return;
}
pushdown(s);
int mid = tr[s].l + tr[s].r >> 1;
if (l <= mid) modify(l, r, val, ls);
if (r > mid) modify(l, r, val, rs);
pushup(s);
}
T query(int l, int r, int s = 1) { // 查找区间总和
if (l <= tr[s].l && tr[s].r <= r) return tr[s].sum;
pushdown(s);
T ans = T();
int mid = tr[s].l + tr[s].r >> 1;
if (l <= mid) ans += query(l, r, ls);
if (r > mid) ans += query(l, r, rs);
return ans;
}
T queryMax(int l, int r, int s = 1) { // 查找区间最大值
if (l <= tr[s].l && tr[s].r <= r) return tr[s].mx;
pushdown(s);
T ans = numeric_limits<T>::min();
int mid = tr[s].l + tr[s].r >> 1;
if (l <= mid) ans = max(ans, queryMax(l, r, ls));
if (mid < r) ans = max(ans, queryMax(l, r, rs));
return ans;
}
T queryMin(int l, int r, int s = 1) { // 查找区间最小值
if (l <= tr[s].l && tr[s].r <= r) return tr[s].mn;
pushdown(s);
int mid = tr[s].l + tr[s].r >> 1;
T ans = numeric_limits<T>::max();
if (l <= mid) ans = min(ans, queryMin(l, r, ls));
if (mid < r) ans = min(ans, queryMin(l, r, rs));
return ans;
}
// ==================================以下都是单点操作=========================================
void add(int p, T val, int s = 1) { // 单点增加一个val值(调用区间修改即可)
update(p, p, val, s);
}
void set(int p, T val, int s = 1) { // 单点设置为固定的值(调用区间设置即可)
modify(p, p, val, s);
}
T queryOne(int p) { // 单点查询(调用区间查询即可)
return query(p, p);
}
};
SegmentTree<int> seg_tree;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
seg_tree.build(1, n);
}
完整的带pushdown和pushup的线段树代码
最新推荐文章于 2024-08-13 14:56:59 发布