線段樹--RMQ

9102700發表於2024-05-04

這是帶上 lazy 標記的線段樹板子

int a[N];

int ls(int p){return p << 1;}
int rs(int p){return p << 1|1;}

class SegmentTree{
public:
	int tree[N << 2|1], tag[N << 2 |1];
	inline void push_up(int p){
		tree[p] = tree[ls(p)] + tree[rs(p)];
	}
	inline void add(int p, int pl, int pr, int d){
		tree[p] += (pr - pl + 1)*d;
		tag[p] += d;
	}
	inline void build(int p, int pl, int pr){
		tag[p] = 0;
		if(pl == pr){
			tree[p] = a[pl];
			return ;
		}
		int mid = (pl + pr) >> 1;
		build(ls(p), pl, mid);
		build(rs(p), mid + 1, pr);
		push_up(p);
	}
	inline void push_down(int p, int pl, int pr){
		if(tag[p]){
			int mid = (pl + pr) >> 1;
			add(ls(p), pl, mid, tag[p]);
			add(rs(p), mid + 1, pr, tag[p]);
			tag[p] = 0;
		}
	}
	inline void update(int L, int R, int p, int pl, int pr, int d){
		if(L <= pl && pr <= R){
			add(p, pl, pr, d);
			return ;
		}
		push_down(p, pl, pr);
		int mid = (pl + pr) >> 1;
		if(L <= mid){
			update(L, R, ls(p), pl, mid, d);
		}
		if(R >= mid + 1){
			update(L, R, rs(p), mid + 1, pr, d);
		}
		push_up(p);
	}
	inline int query(int L, int R, int p, int pl, int pr){
		if(L <= pl && pr <= R){
			return tree[p];
		}
		int mid = (pl + pr) >> 1;
		push_down(p, pl, pr);
		int res = 0;
		if(L <= mid){
			res += query(L, R, ls(p), pl, mid);
		}
		if(R >= mid + 1){
			res += query(L, R, rs(p), mid + 1, pr);
		}
		return res;
	}
};
SegmentTree seg;