校门外的树 区间处理

本文介绍了一种使用线段树解决区间删除问题的方法。通过维护区间内的树节点状态,可以高效地处理区间删除操作,并快速查询剩余树的数量。文章提供了一个具体的例子,展示了如何在给定的区间内进行删除操作并计算剩余树的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述
  某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数 轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
  由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已 知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树 都移走后,马路上还有多少棵树。
输入格式
  输入文件的第一行有两个整数L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点 和终止点的坐标。
输出格式
  输出文件包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
样例输入
500 3
150 300
100 200
470 471
样例输出

298

解题思路:

线段树区间处理问题,顺便自己写了一个线段树当做练手了;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
#define maxn 100000
#define L(a) (a)<<1
#define R(a) (a)<<1|1
struct Node{
	int sum;
	int add;
	int set;
	int left,right;
}node[3*maxn];
int ans;
int a,b;
void create(int num,int l,int r)
{
	node[num].left=l;
	node[num].right=r;
	if(l==r)
	{
		node[num].sum=1;
		node[num].set=-1;
		node[num].add=0;
		return ;
	}
	int mid=(l+r)>>1;
	create(L(num),l,mid);
	create(R(num),mid+1,r);
	node[num].sum=node[L(num)].sum+node[R(num)].sum;
	node[num].set=-1;
	node[num].add=0;

}

void maintain(int num,int l,int r)
{
	node[num].sum=1;
	if(r>l)
	{
		node[num].sum=node[L(num)].sum+node[R(num)].sum;
	}
	
}
void pushup(int num)
{
	node[num].sum=node[L(num)].sum+node[R(num)].sum;
}
void pushdown(int num)
{
	if(node[num].set==0)
	{
		node[L(num)].set=node[R(num)].set=node[num].set;
		node[L(num)].sum=0;
		node[R(num)].sum=0;
		node[num].set=-1;
	}
}
void updata(int num,int l,int r,int v)
{
	if(node[num].left==l&&node[num].right==r)
	{
		node[num].set=v;
		node[num].sum=(r-l+1)*v;
		return ;
	}
	else
	{
		pushdown(num);
		int mid=(node[num].left+node[num].right)>>1;
		if(r<=mid)
		updata(L(num),l,r,v);
		else if(l>mid)
		updata(R(num),l,r,v);
		else
		{
			updata(L(num),l,mid,v);
			updata(R(num),mid+1,r,v);
		}
		pushup(num);
	}
}
void query(int num,int l,int r)
{
	if(node[num].left==l&&node[num].right==r)
	{
		ans+=node[num].sum;
		return ;
	}
	int mid=(node[num].left+node[num].right)>>1;
	if(r<=mid)
	query(L(num),l,r);
	else if(l>mid)
	query(R(num),l,r);
	else
	{
		query(L(num),l,mid);
		query(R(num),mid+1,r);
	}

}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	create(1,0,n);
	ans=0;
	for(int i=0;i<m;i++)
	{
		scanf("%d%d",&a,&b);
		updata(1,a,b,0);
	}
	query(1,0,n);
	printf("%d\n",ans);
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值