线段树模板

一、模板

#define lc(p) p << 1         // 左孩子 
#define rc(p) p << 1 | 1     // 右孩子 
const int MAX = 5e5 + 5;     // 数列元素最大个数 
ll n, m, w[MAX];             // n -- 数列元素个数; m -- 操作数; w[i] -- 第i个元素的值 
struct {int l, r; ll sum, tag;} tree[MAX << 2]; // 一般开元素个数的4倍数组 
// 边界为[l, r]; sum -- 区间和; tag -- 懒标记 

void pushup(int p)
{
	tree[p].sum = tree[lc(p)].sum + tree[rc(p)].sum; // 用区间p的左孩子和右孩子的值更新该区间的值 
}

void pushdown(int p)
{
	if (tree[p].tag) // 向下传递懒标记 
	{
		tree[lc(p)].sum += (tree[lc(p)].r - tree[lc(p)].l + 1) * tree[p].tag;
		tree[lc(p)].tag += tree[p].tag;
		
		tree[rc(p)].sum += (tree[rc(p)].r - tree[rc(p)].l + 1) * tree[p].tag;
		tree[rc(p)].tag += tree[p].tag;
		
		tree[p].tag = 0;
	}
}

void build(int p, int l, int r)
{
	tree[p] = {l, r, w[l], 0};
	if (l == r)    return;
	
	int m = l + r >> 1;          // 递归建立左、右子树 
	build(lc(p), l, m);
	build(rc(p), m + 1, r);
	
	pushup(p); 
}

void update(int p, int x, int y, int k)
{
	if (x <= tree[p].l && tree[p].r <= y)
	{
		tree[p].sum += (tree[p].r - tree[p].l + 1) * k;
		tree[p].tag += k;
		return;
	}
	
	pushdown(p);
	
	int m = tree[p].l + tree[p].r >> 1;
	if (x <= m)    update(lc(p), x, y, k);
	if (y > m)    update(rc(p), x, y, k);
	
	pushup(p);
}

ll query(int p, int x, int y)
{
	if (x <= tree[p].l && tree[p].r <= y)
		return tree[p].sum;
		
	pushdown(p);
	
	int m = tree[p].l + tree[p].r >> 1;
	ll sum = 0;
	if (x <= m)    sum += query(lc(p), x, y);
	if (y > m)    sum += query(rc(p), x, y);
	
	return sum;
}

二、相关例题

P3374 【模板】树状数组 1

P3372 【模板】线段树 1

posted @   ltign  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示