校门外的树 线段树解法

#include <iostream>
#include <cstdio>
using namespace std;
class SegTree
{
public:
	SegTree();
	void Create(int start, int end); //创建线段树
	void Insert(int start, int end); //插入线段
	bool Delete(int start, int end); //删除线段
	int dim;                         //当前所有区间长度和
	int regs;                        //独立区间的个数
	~SegTree();
private:
	void Update();                   //插入删除后更新数据
	SegTree *left;                   //左子树
	SegTree *right;                  //右子树
	char lcov;                       //是否覆盖左端点
	char rcov;                       //是否覆盖右端点
	int lend;                        //左端点
	int rend;                        //右端点
	int count;                       //覆盖区间线段的数目
};


SegTree::SegTree()
{
	left = right = NULL;
	lcov = rcov = 0;
	lend = rend = 0;
	count = 0;
	dim = regs = 0;
}

void SegTree::Create(int start,int end)
{
	rend = end;
	lend = start;
	if(end - start > 0)
	{
		int mid = (lend + rend) / 2;
		left = new SegTree();
		right = new SegTree();
		left->Create(start, mid);
		right->Create(mid + 1, end);
	}
}
void SegTree::Insert(int start,int end)
{
	if(start <= lend && end >= rend)
		count++;//覆盖整条线段
	else //否则二分寻找覆盖区域
	{
		int mid = (lend + rend) / 2;
		if(start <= mid) 
			left->Insert(start, end);
		if(mid < end) 
			right->Insert(start, end);
	}
	Update();
}
bool SegTree::Delete(int start,int end)
{
	if(start <= lend && end >= rend)
	{
		if(count > 0)
			count--;
		else
			return false;
	}
	else
	{
		int mid = (lend + rend) / 2;
		if(start < mid)
		{
			if(!left->Delete(start, end))
				return false;
		}
		if(end > mid)
		{
			if(!right->Delete(start, end))
				return false;
		}
	}
	Update();
	return true;
}

void SegTree::Update()
{
	if(count > 0)                   //有线段覆盖这个区间
	{
		dim = rend - lend + 1;
		lcov = rcov = 1;
		regs = 1;
	}
	else //内部节点且无覆盖
	{
		dim = left->dim + right->dim;
		lcov = left->lcov;
		rcov = right->rcov;
		regs = left->regs + right->regs;           //若左子树覆盖了右端点且右子树覆盖了左端点则区间数-1
	}

}

SegTree::~SegTree()
{
	if(left != NULL)
		delete left;
	if(right != NULL)
		delete right;
}
int main()
{
	//
	int i, j;
	int L, M;
	while(cin >> L >> M)
	{
		SegTree T;
		T.Create(0, L);
		for(i = 0; i < M; i++)
		{
			int s, e;
			cin >> s >> e;
			T.Insert(s, e);
		}
		cout << L - T.dim + 1 << endl;
	}

	///
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值