线段树应用:区间合并

传送门luoguP2894

本题我们要维护最左边的值,考虑使用线段树维护。我们发现只用一个来存储当前的节点的值并不够,因为对于一个节点我们无法用一个来描述这整个区间哪些为空,哪些满了,例如查询的跨越了两个区间,我们就无法找到最左边的了。
所以我们考虑用多个变量描述该区间的状态:
lmx表示该区间最左边连续为空的个数,
rmx表示该区间最右边连续为空的个数,
len表示整个区间的总房间数,
sum表示整个区间的总空房间数。
这样我们可以很好的描述状态了,
对于一个节点的左房间数等于t[k].lmx,
若左儿子全空即t[lc].len=t[lc].sum,那么t[k].lmx=t[lc].sum+t[rc].lmx,
同理于右节点。
对于横跨两个节点的区间,
等于t[lc].rmx+t[rc].lmx左儿子的右房间数+右儿子的左房间数,
由于是区间更新,所以我们还要使用lazy_tag来做,
核心介绍完了,代码实现:

#include<bits/stdc++.h>
using namespace std;
#define lc k<<1
#define rc k<<1|1

const int N=5e5+5;
int n,m;
struct node
{
   
	int lz,sum,len,lmx,rmx,l,r;
	//该节点懒惰标记,最大连续空房间数,房间总数,左边连续空房间数,右边连续空房间数 
}t[N<<2];//4倍以上 

inline void pushdown(int k)
{
   
	if(t[k].lz==0) return;
	if(t[k].lz==1)//开房 
	{
   
		t[lc].lz=t[rc].lz=1;
		t[lc].lmx=t[lc].rmx=t[lc].sum=0;
		t[rc].lmx=t[rc].rmx=t[rc].sum=0;
	}
	if(t[k].lz==2
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值