线段树模板(维护区间最大值,区间和,主席树)

维护区间最大值 

//维护区间最大值的线段树
struct SEG
{
	int t[N << 2];
	void up(int p) { t[p] = max(t[p << 1], t[p << 1 | 1]); }
	void build(int p, int l, int r){
		if (l == r)
		{
			t[p] = c;
			return;
		}
		int mid = l + r >> 1;
		build(p << 1, l, mid);
		build(p << 1 | 1, mid + 1, r);
		up(p);
	}
	void update(int p, int l, int r,int f, int x){
		if (l == r)
		{
			t[p] -= x;
			return;
		}
		int mid = l + r >> 1;
		if (f<=mid)update(p << 1, l, mid, f, x);
		else if(f>mid) update(p << 1|1, mid+1, r, f, x);
		up(p);
	}
	//单点查询(查询第一个大于等于数x的位置)
	int query(int p, int l, int r, int x)
	{
		if (l == r)return l;
		int mid = l + r >> 1;
		int res;
		if (x <= t[p << 1])res=query(p << 1, l, mid, x);
		else if(x<=t[p<<1|1]) res=query(p << 1 | 1, mid + 1, r, x);
		return res;
	}
	//区间查询(查询区间a,b的最大值)
	int xquery(int p,int l,int r,int a,int b)
	{
	    int ans = -1;
		if (a <= l && r <= b)
		{
			return t[p];
		}
		int mid = (l + r) / 2;
		if (a <= mid)ans = max(ans, xquery(p<<1, l, mid, a, b));
		if (b > mid)ans = max(ans, xquery(p<<1|1, mid + 1, r, a, b));
		return ans;
	}
}seg;

维护区间和

struct node
{
	int l, r;
	int lz;//lazy标志,所加数的大小被存入lz中;
	ll  sum;
}tr[4 * N];//线段树一般开4倍的空间

void build(int i, int l, int r)
{
	tr[i].l = l; tr[i].r = r; tr[i].lz = 0;
	if (l == r)
	{
		tr[i].sum = a[l];
		return;
	}
	int mid = (r + l) / 2;
	build(i * 2, l, mid);
	build(i * 2 + 1, mid + 1, r);
	tr[i].sum = tr[i * 2].sum + tr[i * 2 + 1].sum;
}
void push_down(int i)
{
	if (tr[i].lz != 0)//此处不能写if(!tr[i].lz)修改值可能为负值
	{
		tr[i * 2].lz += tr[i].lz;
		tr[i * 2 + 1].lz += tr[i].lz;
		int mid = (tr[i].l + tr[i].r) / 2;
		tr[i * 2].sum += tr[i].lz * (mid - tr[i * 2].l + 1);
		tr[i * 2 + 1].sum += tr[i].lz * (tr[i * 2 + 1].r - mid);
		tr[i].lz = 0;
	}
	return;
}
void add(int i, int l, int r, int k)
{
	if (tr[i].l >= l && tr[i].r <= r)
	{
		tr[i].sum += k * (tr[i].r - tr[i].l + 1);
		tr[i].lz += k;
		return;
	}
	push_down(i);
	if (tr[i * 2].r >= l)
		add(i * 2, l, r, k);
	if (tr[i * 2 + 1].l <= r)
		add(i * 2 + 1, l, r, k);
	tr[i].sum = tr[i * 2].sum + tr[i * 2 + 1].sum;
	return;
}
long long query(int i, int l, int r)
{
	if (tr[i].l >= l && tr[i].r <= r)
		return tr[i].sum;
	push_down(i);
	long long ans = 0;
	if (tr[i * 2].r >= l)
		ans += query(i * 2, l, r);
	if (tr[i * 2 + 1].l <= r)
		ans += query(i * 2 + 1, l, r);
	return ans;
}
主席树
2022/5/6 鸽了,学线代去了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值