Hotel 旅馆, 线段树查询,合并
C. Hotel 旅馆
题目描述
OIER最近的旅游计划,是到长春净月潭,享受那里的湖光山色,以及明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿。这个巨大的旅馆一共有N
间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的湖面。 所有的旅游者,都是一批批地来到旅馆的服务台,希望能订到 间连续的房间。服务台的接待工作也很简单:如果存在r满足编号为 的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。 旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字 、 描述,表示编号为 房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。 而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理
个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。
输入格式
第1行: 2个用空格隔开的整数:N、M
第2..M+1行: 第i+1描述了第i个请求,如果它是一个订房请求,则用2个数字 1、
描述,数字间用空格隔开;如果它是一个退房请求,用3 个以空格隔开的数字
、 、 描述
输出格式
第1..??行: 对于每个订房请求,输出1个独占1行的数字:如果请求能被满足 ,输出满足条件的最小的r;如果请求无法被满足,输出0
样例
样例输入
10 6
1 3
1 3
1 3
1 3
2 5 5
1 6
样例输出
1
4
7
0
5
线段树区间合并裸题 我们设这样几个数组 : max_near、max_l、max_r、lazy来分别表示区间最大连续长度,从左开始的最大连续长度,从右开始的区间最大连续长度、懒度标记
这样 我们的max_near就是max(max(max_near[lc],max_near[rc]),max_r[lc]+max_r[lc]) 对于max_l的维护,若左儿子的max_next等于len,那么就是左儿子的len加右儿子max_l,否则是左儿子的max_l,max_r类似。
对于每次查询,如果max_near[root] < query ,那么直接输出0即可,否则的话以 左子树? 左子树右加右子树左 ? 右子树的顺序选择递归,返回ans并从ans+query的区间范围对树进行修改。
代码:
#include<bits/stdc++.h>
#define re register int
using namespace std;
int n,m,o;
int a,d,x,maxx;
int max_near[500100],max_l[500100],max_r[500100],len[500100],lazy[500100],cl[500100],cr[500100];
void pp(int k)
{
max_l[k]=max_l[k<<1];
max_r[k]=max_r[k<<1|1];
if(max_l[k]==(cr[k<<1]-cl[k<<1]+1))
max_l[k]+=max_l[k<<1|1];
if(max_r[k]==(cr[k<<1|1]-cl[k<<1|1]+1))
max_r[k]+=max_r[k<<1];
max_near[k]=max(max_r[k<<1]+max_l[k<<1|1],max(max_near[k<<1],max_near[k<<1|1]));
/*
错误搞法
len[k]=len[k<<1]+len[k<<1|1];
max_l[k]=(max_near[k<<1]==len[k<<1])?(len[k<<1]+max_l[k<<1|1]):max_l[k<<1];
max_r[k]=(max_near[k<<1|1]==len[k<<1|1])?(len[k<<1|1]+max_r[k<<1]):max_r[k<<1|1];
max_near[k]=max_r[k<<1]+max_l[k<<1|1];
*/
return;
}
void build(int k,int l,int r)
{
cl[k]=l;
cr[k]=r;
lazy[k]=-1;
if(l==r)
{
max_l[k]=max_r[k]=max_near[k]=len[k]=1;
return;
}
int m=(l+r)>>1;
build(k<<1,l,m);
build(k<<1|1,m+1,r);
pp(k);
}
void pushdown(int r,int lc,int rc)
{
if(lazy[r]!=-1)
{
lazy[lc]=lazy[rc]=lazy[r];
if(lazy[r])
{
max_near[lc]=max_l[lc]=max_r[lc]=len[lc]=0;
max_near[rc]=max_l[rc]=max_r[rc]=len[rc]=0;
}
else
{
max_near[lc]=max_l[lc]=max_r[lc]=len[lc]=cr[lc]-cl[lc]+1;
max_near[rc]=max_l[rc]=max_r[rc]=len[rc]=cr[rc]-cl[rc]+1;
}
lazy[r]=-1;
}
}
int que(int k,int d)
{
int m=(cl[k]+cr[k])>>1;
if(cl[k]==cr[k])
return cl[k];
/*
错误,因为开端不一定在最左边!
if(max_near[k]==d)
return cl[k];
*/
pushdown(k,k<<1,k<<1|1);
if(max_near[k<<1]>=d)
return que(k<<1,d);
if(max_r[k<<1]+max_l[k<<1|1]>=d)
return m-max_r[k<<1]+1;
else
return que(k<<1|1,d);
}
void updata(int l,int r,int root,int z)
{
if(l<=cl[root]&&cr[root]<=r)
{
lazy[root]=z;
if(z)
max_near[root]=max_l[root]=max_r[root]=len[root]=0;
else
max_near[root]=max_l[root]=max_r[root]=len[root]=cr[root]-cl[root]+1;
return;
}
int m=(cr[root]+cl[root])>>1;
pushdown(root,root<<1,root<<1|1);
if(m>=l)
updata(l,r,root<<1,z);
if(m<r)
updata(l,r,root<<1|1,z);
pp(root);
}
int qian(int x)
{
if(cl[x<<1])
qian(x<<1);
if(cl[x<<1|1])
qian(x<<1|1);
}
int main()
{
scanf("%d%d",&n,&m);
build(1,1,n);
for(re i=1;i<=m;i++)
{
scanf("%d",&a);
if(a==1)
{
scanf("%d",&d);
if(max_near[1]<d)
{
printf("0\n");
continue;
}
o=que(1,d);
printf("%d\n",o);
updata(o,o+d-1,1,1);
}
else
{
scanf("%d%d",&x,&d);
updata(x,x+d-1,1,0);
}
}
return 0;
}
Hotel 旅馆, 线段树查询,合并的更多相关文章
- 【bzoj1593】[Usaco2008 Feb]Hotel 旅馆 线段树区间合并
题目描述 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N & ...
- Poj 3667——hotel——————【线段树区间合并】
Hotel Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 13124 Accepted: 5664 Descriptio ...
- poj3667 Hotel (线段树 区间合并)
poj3667 HotelTime Limit: 3000MS Memory Limit: 65536KTotal Submissions: 18925 Accepted: 8242Descripti ...
- poj 3667 Hotel (线段树的合并操作)
Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...
- POJ 3667 Hotel(线段树+区间合并)
http://poj.org/problem?id=3667 题意: 有N个房间,M次操作.有两种操作(1)"1a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示 ...
- BZOJ 1593: [Usaco2008 Feb]Hotel 旅馆 [线段树]
传送门 题意: 操作1:找长为$len$的空区间并填满,没有输出$0$ 操作2:将$[l,r]$之间的区间置空 我真是太弱了这种线段树还写了一个半小时,中间为了查错手动模拟了$30min$线段树操作, ...
- bzoj1593 [Usaco2008 Feb]Hotel 旅馆(线段树)
1593: [Usaco2008 Feb]Hotel 旅馆 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 758 Solved: 419[Submit ...
- POJ 3667 Hotel (线段树区间合并)
题目链接:http://poj.org/problem?id=3667 题目大意:一共有n个房间,初始时都是空的,现在有m个操作,操作有以下两种: 1.1 d :询问是否有连续d个空的房间,若有则输出 ...
- (简单) POJ 3667 Hotel,线段树+区间合并。
Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and e ...
随机推荐
- RobotFramework + Python 自动化入门 二 (关键字)
在<RobotFramwork + Python 自动化入门 一>中,完成了Robot环境搭建及测试脚本的创建和执行. 本节,对RobotFramework的关键字使用和查看源码进行介绍. ...
- VRRP协议与原理
VRRP协议与原理 目录: 一.VRRP协议概述 1.1.VRRP协议 1.2.单网关和多网关的缺陷 1.3.VRRP基本概述 二.VRRP工作原理 2.1.VRRP主备份备份工作工程 2.2.VRR ...
- 开源版本的 uTools。可支持 uTools 所有插件生态
话不多说,先放上截图和仓库地址: 代码仓库:github 故事背景 网络抓包 之前公司内部因为开发需要,需要和后端进行接口联调,测试环境的时候,经常会涉及到一些状态改变要看交互样式的问题.比如测试需要 ...
- 在C++中,你真的会用new吗?
摘要:"new"是C++的一个关键字,同时也是操作符.关于new的话题非常多,因为它确实比较复杂,也非常神秘. 本文分享自华为云社区<如何编写高效.优雅.可信代码系列(2)- ...
- 用jquery通过点击事件把下拉列表币种的值传给文本框1,再通过文本框1的币种名称用if转化为币别传值给文本框2保存
<script src="https://cdn.staticfile.org/jquery/2.2.4/jquery.min.js"></script>& ...
- Python UI自动化
Python3--Uiautomator2--Pytest--Alure使用 官方源码GitHub地址:https://github.com/openatx/uiautomator2 介绍 uiaut ...
- 07 修改JumpServer网页信息
1.7.修改JumpServer网页信息 注意:在修改相关配置文件之前要先进行备份,防止文件修改错误无法恢复. 1.Luna图标: /opt/luna/static/imgs/logo.png 2.j ...
- mui 移动端网页双击事件处理
使用场景:需要在动态生成li列表数据中添加双击事件 定义事件 : var date1=null; function listdb(myKey) { var date2 = new Date(); if ...
- hdu 3306 Another kind of Fibonacci 矩阵快速幂
参考了某大佬的 我们可以根据(s[n-2], a[n-1]^2, a[n-1]*a[n-2], a[n-2]^2) * A = (s[n-1], a[n]^2, a[n]*a[n-1], a[n-1] ...
- 前端笔记:Html页面常用元素
Html页面由基本几个元素(标签)组成 html.head.body.foot(很少使用). html是整个页面的父级元素,内部包括head.body.foot子类标签. head是页头,及页面的头部 ...