POJ 3667 线段树区间合并

本文介绍了一种用于旅馆房间管理的高效算法,通过引入三个数组:lsum、rsum 和 sum,来实现快速查询和更新操作。该算法特别针对输入指令1b表示入住、指令2bc表示清空房间区间的需求,通过更新这些数组来实现房间的有效管理和资源分配。

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

题意:一个旅馆有n个房间,m条操作,如果输入1 b  表示住进来b个人  然后输出这b个人住的房间编号最前面的那个,如果输入 2 b c, 就是说要将b到b+c-1的房间全部全部清空。

思路:此题更新操作简单,但是查询的时候不好做,这题要添加两个数组,lsum表示一个区间从最左端开始可用的且连续的最大长度,例如区间[1,5],覆盖情况为[0,0,0,1,1],lsum=3,从最左端有3格可以利用。区间[1,5],覆盖情况为[1,0,0,0,0],lsum=0,因为从最左端开始找不到1格可用的区间rsum表示到当前节点为止的最长连续的房间个数。rsum表示一个区间从最右端开始可用的且连续的最大长度。例如区间[1,5],覆盖情况为[1,0,1,0,0],rsum=2,从最右端有2格可以利用。区间[1,5],覆盖情况为[0,0,0,0,1],rsum=0,因为从最右端开始找不到可用的区间。而sum存该区间最大的长度。

对于一个区间,我们知道它左半区间的sum,和右半区间的sum,如果左半区间的sum>=W,那么我们一定能在左边找到,所以可以到左半区间去确定该区间的具体位置,如果左端的不满足,那么我们要先考虑横跨两边的区间,一段横跨的区间,那么是左边区间的rsum+右边区间的lsum,如果满足的话,就是该区间了,它的位置也是可以确定的。如果横跨的区间不满足,那么就在右半区间找,如果右半区间的sum>=w, 那么可以在右半区间找到,所以到右半区间去确定它的具体位置。

接下来要说的就是对这三个值进行更新,当前区间的sum=max{左区间的rsum+右区间的lsum,max{左区间的sum,右区间的sum}};

如果左区间全部都可以用,那么当前的lsum=左区间lsum+右区间lsum,不然的话,就表示只有部分房间可以用,那么当前lsum=左区间lsum。

同理如果右区间全部都可以用,当前rsum=右区间rsum+左区间rsum,不然就是当前rsum=右边rsum

#include <stdio.h>
#include <algorithm>
using namespace std;

#define maxn 55555

int lsum[maxn<<2],rsum[maxn<<2],sum[maxn<<2];
int lazy[maxn<<2];
int L,R;

void pushdown(int id,int m)//向下更新。 
{
	if(lazy[id]!=-1)
	{
		lazy[id<<1]=lazy[id<<1|1]=lazy[id];
		sum[id<<1]=lsum[id<<1]=rsum[id<<1]=lazy[id]?0:m-(m>>1);//如果lazy的值不是0就归0,不然就赋值 m-(m>>1)
		sum[id<<1|1]=lsum[id<<1|1]=rsum[id<<1|1]=lazy[id]?0:m>>1;
		lazy[id]=-1;
	}
}

void pushup(int id,int m)//更新三个数组的值 
{
	lsum[id]=lsum[id<<1];
	rsum[id]=rsum[id<<1|1];
	if(lsum[id]==m-(m>>1))
	lsum[id]+=lsum[id<<1|1];
	if(rsum[id]==m>>1)
	rsum[id]+=rsum[id<<1];
	sum[id]=max(lsum[id<<1|1]+rsum[id<<1],max(sum[id<<1],sum[id<<1|1]));
}

void build(int l,int r,int id)
{
	lazy[id]=-1;
	sum[id]=lsum[id]=rsum[id]=r-l+1;
	if(l==r)return ;
	int mid=l+r>>1;
	build(l,mid,id<<1);
	build(mid+1,r,id<<1|1);
}

void updata(int c,int l,int r,int id)
{
	if(L<=l&&r<=R)
	{
		sum[id]=lsum[id]=rsum[id]=c?0:r-l+1;
		lazy[id]=c;
		return ;
	}
	pushdown(id,r-l+1);
	int mid=l+r>>1;
	if(L<=mid)updata(c,l,mid,id<<1);
	if(R>mid)updata(c,mid+1,r,id<<1|1);
	pushup(id,r-l+1);
}

int query(int w,int l,int r,int id)
{
	if(l==r)return l;
	pushdown(id,r-l+1);//这里也要pushdown ,开始漏掉WA了 
	int mid=l+r>>1;
	if(sum[id<<1]>=w)
	return query(w,l,mid,id<<1);
	else if(lsum[id<<1|1]+rsum[id<<1]>=w)//横跨区间直接返回,开始用递归的结果错了 QAQ 现在都没有想出来为什么 
	return mid-rsum[id<<1]+1;
	return query(w,mid+1,r,id<<1|1);
}

int main()
{
	int m,n,op,a,b;
	scanf("%d %d",&n,&m);
	build(1,n,1);
	while(m--)
	{
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d",&a);
			if(sum[1]<a)puts("0");
			else 
			{
				int p=query(a,1,n,1);
				printf("%d\n",p);
				L=p;
				R=p+a-1;
				updata(1,1,n,1);
			}
		}
		else 
		{
			scanf("%d %d",&a,&b);
			L=a;
			R=a+b-1;
			updata(0,1,n,1);
		}
	}
	return 0;
}



资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在 IT 领域,文档格式转换是常见需求,尤其在处理多种文件类型时。本文将聚焦于利用 Java 技术栈,尤其是 Apache POI 和 iTextPDF 库,实现 doc、xls(涵盖 Excel 2003 及 Excel 2007+)以及 txt、图片等格式文件向 PDF 的转换,并实现在线浏览功能。 先从 Apache POI 说起,它是一个强大的 Java 库,专注于处理 Microsoft Office 格式文件,比如 doc 和 xls。Apache POI 提供了 HSSF 和 XSSF 两个 API,其中 HSSF 用于读写老版本的 BIFF8 格式(Excel 97-2003),XSSF 则针对新的 XML 格式(Excel 2007+)。这两个 API 均具备读取和写入工作表、单元格、公式、样式等功能。读取 Excel 文件时,可通过创建 HSSFWorkbook 或 XSSFWorkbook 对象来打开相应格式的文件,进而遍历工作簿中的每个 Sheet,获取行和列数据。写入 Excel 文件时,创建新的 Workbook 对象,添加 Sheet、Row 和 Cell,即可构建新 Excel 文件。 再看 iTextPDF,它是一个用于生成和修改 PDF 文档的 Java 库,拥有丰富的 API。创建 PDF 文档时,借助 Document 对象,可定义页面尺寸、边距等属性来定制 PDF 外观。添加内容方面,可使用 Paragraph、List、Table 等元素将文本、列表和表格加入 PDF,图片可通过 Image 类加载插入。iTextPDF 支持多种字体和样式,可设置文本颜色、大小、样式等。此外,iTextPDF 的 TextRenderer 类能将 HTML、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值