求助站外题(线段树)
  • 板块学术版
  • 楼主Aishiteru_zwy
  • 当前回复2
  • 已保存回复2
  • 发布时间2022/8/2 13:27
  • 上次更新2023/10/27 17:23:08
查看原帖
求助站外题(线段树)
369479
Aishiteru_zwy楼主2022/8/2 13:27

【题目描述】:

奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿。这个巨大的旅馆一共有N 间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的湖面。

贝茜一行,以及其他慕名而来的旅游者,都是一批批地来到旅馆的服务台,希望能订到D_i (1 <= D_i <= N)间连续的房间。服务台的接待工作也很简单:如果存在r满足编号为r..r+D_i-1的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。

旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字X_i、D_i描述,表示编号为X_i..X_i+D_i-1 (1 <= X_i <= N-D_i+1)房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。

而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理M 个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。

【输入描述】:

第一行输入n,m ,n代表有n个房间,编号为1---n,开始都为空房,m表示以下有m行操作,以下 每行先输入一个数 i ,表示一种操作:

若i为1,表示查询房间,再输入一个数x,表示在1--n 房间中找到长度为x的连续空房,输出连续x个房间中左端的房间号,尽量让这个房间号最小,然后入住。若找不到长度为x的连续空房,输出0。

若i为2,表示退房,再输入两个数 x,y 代表 房间号 x---x+y-1 退房,即让房间为空。

【输出描述】:

对于每一个入住请求,输出查询出可以入住的最小房间号,如果不能安排入住输出0;

【样例输入】:

10 6

1 3

1 3

1 3

1 3

2 5 5

1 6

【样例输出】:

1

4

7

0

5

【时间限制、数据范围及描述】:

时间:1s 空间:128M

对于30%的数据:1≤N≤100;1≤M≤100;

对于60%的数据:1≤N≤1000;1≤M≤1000;

对于80%的数据:1≤N≤10000;1≤M≤10000;

对于100%的数据:1≤N≤50,000;1≤M<50,000

#include "cstdio"
using namespace std;
void read (int &a){
	int k=1;a=0;
	char c=getchar();
	while (c<48||c>57){if (c=='-') k=-1;c=getchar();}
	while (c>=48&&c<=57){a=a*10+c-'0';c=getchar();}
	a*=k;
}

int max (int x,int y){
	return x>y?x:y;
}

struct tree{
	int lay,s,ln,rn,l,r;
}tr[200005];

void pushup (int u){
	if (tr[u<<1].ln==tr[u<<1].r-tr[u<<1].l+1) tr[u].ln=tr[u<<1].ln+tr[u<<1|1].rn;
	else tr[u].ln=tr[u<<1].ln;
	if (tr[u<<1|1].rn==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].rn=tr[u<<1|1].rn+tr[u<<1].rn;
	else tr[u].rn=tr[u<<1|1].rn;
	tr[u].s=max(tr[u<<1].rn+tr[u<<1|1].ln,max(tr[u<<1].s,tr[u<<1|1].s));
}

void build (int l,int r,int u){
	tr[u].s=tr[u].ln=tr[u].rn=tr[u].s=r-l+1;
	tr[u].l=l;
	tr[u].r=r;
	tr[u].lay=0;
	if (l==r) return;
	int m=l+r>>1;
	build(l,m,u<<1);build(m+1,r,u<<1|1);
}

void pushdown (int l,int r,int u){
	if (l==r||!tr[u].lay) return;
	if (tr[u].lay==1){
		tr[u<<1].lay=tr[u<<1|1].lay=1;
		tr[u<<1].ln=tr[u<<1].rn=tr[u<<1].s=tr[u<<1].r-tr[u<<1].l+1;
		tr[u<<1|1].ln=tr[u<<1|1].rn=tr[u<<1|1].s=tr[u<<1|1].r-tr[u<<1|1].l+1;
	}
	else{
		tr[u<<1].lay=tr[u<<1|1].lay=2;
		tr[u<<1].ln=tr[u<<1].rn=tr[u<<1].s=0;
		tr[u<<1|1].ln=tr[u<<1|1].rn=tr[u<<1|1].s=0;
	}
	tr[u].lay=0;
}

void update (int L,int R,int x,int l,int r,int u){
	if (L<=l&&r<=R){
		tr[u].lay=x;
		if (x==1) tr[u].ln=tr[u].rn=tr[u].s=r-l+1;
		else tr[u].ln=tr[u].rn=tr[u].s=0;
		return;
	}
	int m=l+r>>1;
	pushdown(l,r,u);
	if (L<=m) update(L,R,x,l,m,u<<1);
	if (R>m) update(L,R,x,m+1,r,u<<1|1);
	pushup(u);
}

int query (int len,int l,int r,int u){
	int m=l+r>>1;
	pushdown(l,r,u);
	if (tr[u<<1].s>=len) return query(len,l,m,u<<1);
	if (tr[u<<1].rn+tr[u<<1|1].ln>=len) return m-tr[u<<1].rn+1;
	return query(len,m+1,r,u<<1|1);
}

int main (){
//	freopen("hotel.in","r",stdin);
//	freopen("hotel.out","w",stdout);
	int n,m,a,b,c;
	read(n);read(m);
	build(1,n,1);
	for (int i=1;i<=m;i++){
		read(a);
		if (a==1){
			read(b);
			if (tr[1].s<b) puts("0");
			else{
				c=query(b,1,n,1);
				printf ("%d\n",c);
				update(c,c+b-1,2,1,n,1);
			}
		}
		else{
			read(b);read(c);
			update(b,b+c-1,1,1,n,1);
		}
	}
	return 0;
}

只有20分,希望有大佬能帮帮我,谢谢了

2022/8/2 13:27
加载中...