【线段树】 HDOJ 5367 digger

本文深入探讨了线段树区间合并的概念、原理及应用,通过实例代码展示了如何使用线段树解决区间操作问题,重点讲解了节点更新、区间查询和合并策略,适合对数据结构和算法感兴趣的读者。

线段树区间合并。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn = 30000005;

struct node
{
	int l, r, l_h, r_h, l_c, r_c, l_s, r_s, delta, ans;
	node *lson, *rson;
}pool[maxn], *tail, *root;

int n, m, R;

node* newnode(int l, int r, int h)
{
	tail->l = l, tail->r = r;
	tail->l_h = tail->r_h = h;
	tail->l_s = tail->r_s = 0;
	tail->l_c = tail->r_c = r - l + 1;
	tail->lson = tail->rson = 0;
	tail->delta = tail->ans = 0;
	return tail++;
}

void init()
{
	tail = pool;
	root = newnode(1, n, R);
}

void pushup(node *o)
{
	o->ans = o->lson->ans + o->rson->ans;
	o->l_h = o->lson->l_h;
	o->r_h = o->rson->r_h;
	o->l_c = o->lson->l_c;
	o->r_c = o->rson->r_c;

	if(o->lson->r_h == o->rson->l_h) {
		if(o->lson->r_s == 1 && o->rson->l_s == 1) o->ans += o->lson->r_c + o->rson->l_c;
		
		if(o->rson->r_s == 0) o->r_s = o->lson->r_s, o->r_c += o->lson->r_c;
		else o->r_s = o->rson->r_s;
		
		if(o->lson->l_s == 0) o->l_s = o->rson->l_s, o->l_c += o->rson->l_c;
		else o->l_s = o->lson->l_s;
	}
	else if(o->lson->r_h > o->rson->l_h) {
		if(o->rson->l_s == 1) o->ans += o->rson->l_c;
		
		if(o->lson->l_s == 0) o->l_s = 2;
		else o->l_s = o->lson->l_s;

		if(o->rson->r_s == 0) o->r_s = 1;
		else o->r_s = o->rson->r_s;
	}
	else {
		if(o->lson->r_s == 1) o->ans += o->lson->r_c;
		
		if(o->lson->l_s == 0) o->l_s = 1;
		else o->l_s = o->lson->l_s;

		if(o->rson->r_s == 0) o->r_s = 2;
		else o->r_s = o->rson->r_s;
	}
}

void pushdown(node *o)
{
	if(o->delta) {
		if(!o->lson) o->delta = 0;
		else {
			o->lson->l_h += o->delta;
			o->lson->r_h += o->delta;
			o->lson->delta += o->delta;

			o->rson->l_h += o->delta;
			o->rson->r_h += o->delta;
			o->rson->delta += o->delta;
		
			o->delta = 0;
		}
	}
}

void update(node *o, int ql, int qr, int v)
{
	if(ql <= o->l && qr >= o->r) {
		o->delta += v;
		o->l_h += v;
		o->r_h += v;
		return;
	}
	pushdown(o);
	
	int mid = o->l + (o->r - o->l) / 2;
	
	if(!o->lson) {
		o->lson = newnode(o->l, mid, o->l_h);
		o->rson = newnode(mid+1, o->r, o->l_h);
	}
	if(ql <= mid) update(o->lson, ql, qr, v);
	if(qr > mid) update(o->rson, ql, qr, v);
	pushup(o);
}

void work()
{
	int ans = 0, ql, qr, v;
	while(m--) {
		scanf("%d%d%d", &ql, &qr, &v);
		
		ql ^= ans, qr ^= ans, v ^= ans;
		update(root, ql, qr, -v);
		printf("%d\n", ans = root->ans);
	}
}

int main()
{
	while(scanf("%d%d%d", &n, &m, &R) != EOF) {
		init();
		work();
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值