完整的带pushdown和pushup的线段树代码

#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);
}

总结自大佬的博客CCF-CSP认证考试 202403-5 文件夹合并 100分题解-CSDN博客

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值