Description

The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as their vacation residence. This immense hotel has N (1 ≤ N ≤ 50,000) rooms all located on the same side of an extremely long hallway (all the better to see the lake, of course).

The cows and other visitors arrive in groups of size Di (1 ≤ Di ≤ N) and approach the front desk to check in. Each group i requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers r..r+Di-1 if they are available or, if no contiguous set of rooms is available, politely suggests alternate lodging. Canmuu always chooses the value of r to be the smallest possible.

Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi and Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+1). Some (or all) of those rooms might be empty before the checkout.

Your job is to assist Canmuu by processing M (1 ≤ M < 50,000) checkin/checkout requests. The hotel is initially unoccupied.

                              --by POJ

http://poj.org/problem?id=3667



给定初始值全0的区间[1,n],支持两种操作:

1 w //查询整个区间最左端长度为w的连续0区间,输出其左端点,并把她全变成1,不存在,则输出0
2 l len //把以l为左端点长度为len的区间清零
 
考虑线段树维护区间:
max:区间最长连续0;
lmax:区间左起最长连续0;
rmax:区间右起最长连续0;
然后把1操作拆成先查询再在此基础上修改,这样修改可与2操作共用函数
查询时
优先递归左半区间,
左区间max非法,则查询左区间rmax+右区间lmax,
再非法,则递归右半区间,
再非法,则返回0,
修改则走线段树正常区间修改流程,打标记什么的;
注意如果查询失败,记得不能进行修改;
然后,如果查到了单点,记得特判一下;
一开始,我想当然的想为1操作定义一个函数,为2操作定义一个函数;
这样第一个函数一边查询一边修改
然而这样就需要打各种各样修改位置不同的标记——因为查询的递归与修改的递归流程很不相似
废了好久,
然后才知道可以这样定函数,
重构,然后清晰了许多;
代码能力不够啊;
代码如下:
 #include<cstdio>
using namespace std;
int n,m,L,R;
struct tree{
int lmax,rmax,max,lz;
}line[];
void builine(int ,int ,int );
void up(int ,int ,int );
void down(int ,int ,int );
int search(int ,int ,int ,int );
void change(int ,int ,int ,int );
int main()
{
int i,j,k,ans;
scanf("%d%d",&n,&m);
builine(,n,);
for(i=;i<=m;i++){
scanf("%d",&j);
if(j==){
scanf("%d",&k);
ans=search(,n,,k);
printf("%d\n",ans);
L=ans;R=L+k-;
if(L)
change(,n,,);
}
else{
scanf("%d%d",&L,&k);
R=L+k-;
change(,n,,);
}
}
}
void builine(int l,int r,int nu){
if(l==r){
line[nu].lmax=line[nu].rmax=line[nu].max=;
return ;
}
int mid=(l+r)>>;
builine(l,mid,nu<<);
builine(mid+,r,nu<<|);
line[nu].lmax=line[nu].rmax=line[nu].max=line[nu<<].max+line[nu<<|].max;
}
void up(int l,int r,int nu){
int mid=(l+r)>>;
if(line[nu<<].max>line[nu<<|].max)
line[nu].max=line[nu<<].max;
else
line[nu].max=line[nu<<|].max;
if(line[nu].max<line[nu<<].rmax+line[nu<<|].lmax)
line[nu].max=line[nu<<].rmax+line[nu<<|].lmax;
line[nu].lmax=line[nu<<].lmax==(mid-l+)?line[nu<<].lmax+line[nu<<|].lmax:line[nu<<].lmax;
line[nu].rmax=line[nu<<|].rmax==(r-mid)?line[nu<<|].rmax+line[nu<<].rmax:line[nu<<|].rmax;
}
void down(int l,int r,int nu){
int mid=(l+r)>>;
if(line[nu].lz){
line[nu<<].lmax=line[nu<<].max=line[nu<<].rmax=((line[nu].lz-)^)*(mid-l+);
line[nu<<|].lmax=line[nu<<|].max=line[nu<<|].rmax=((line[nu].lz-)^)*(r-mid);
line[nu<<].lz=line[nu<<|].lz=line[nu].lz;
line[nu].lz=;
}
}
int search(int l,int r,int nu,int len){
int mid=(l+r)>>,ans;
down(l,r,nu);
if(l==r)
return line[nu].max*l;
if(line[nu<<].max>=len){
ans=search(l,mid,nu<<,len);
return ans;
}
if(line[nu<<].rmax+line[nu<<|].lmax>=len){
ans=mid-line[nu<<].rmax+;
return ans;
}
if(line[nu<<|].max>=len){
ans=search(mid+,r,nu<<|,len);
return ans;
}
return ;
}
void change(int l,int r,int nu,int x){
if(L<=l&&r<=R){
line[nu].lmax=line[nu].rmax=line[nu].max=(r-l+)*(x^);
line[nu].lz=x+;
return ;
}
down(l,r,nu);
int mid=(l+r)>>;
if(L<=mid)
change(l,mid,nu<<,x);
if(R>mid)
change(mid+,r,nu<<|,x);
up(l,r,nu);
}

祝AC

POJ P3667 Hotel——solution的更多相关文章

  1. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  2. POJ 3667 Hotel(线段树)

    POJ 3667 Hotel 题目链接 题意:有n个房间,如今有两个操作 1.找到连续长度a的空房间.入住,要尽量靠左边,假设有输出最左边的房间标号,假设没有输出0 2.清空[a, a + b - 1 ...

  3. poj 3667 Hotel (线段树)

    http://poj.org/problem?id=3667 Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 94 ...

  4. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  5. poj 3667 Hotel(线段树,区间合并)

    Hotel Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 10858Accepted: 4691 Description The ...

  6. POJ 3667 Hotel (线段树区间合并)

    题目链接:http://poj.org/problem?id=3667 最初给你n间空房,m个操作: 操作1 a 表示检查是否有连续的a间空房,输出最左边的空房编号,并入住a间房间. 操作2 a b ...

  7. (简单) POJ 3667 Hotel,线段树+区间合并。

    Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and e ...

  8. POJ 3667 Hotel(线段树+区间合并)

    http://poj.org/problem?id=3667 题意: 有N个房间,M次操作.有两种操作(1)"1a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示 ...

  9. Poj 3667——hotel——————【线段树区间合并】

    Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13124   Accepted: 5664 Descriptio ...

随机推荐

  1. 本机号码认证黑科技:极光(JG)开发者服务推出“极光认证”新产品

    近日,中国领先的大数据服务商极光(JG)推出全新产品--极光认证JVerification.极光认证是极光针对APP用户注册登陆,二次安全验证等身份验证场景打造的一款本机号码认证SDK,验证用户提供的 ...

  2. Bootstrap Modal 关闭时右侧滚动条消失,页面左移的解决方法

    问题描述:页面在打开Modal之前右侧有滚动条,Modal关闭之后,body中的class="modal-open"和style="padding-right: 17px ...

  3. Linux系统NAT模式下设置网络网关

    1.配置Vm网络编辑器 2.配置固定IP地址 命令:vi /etc/sysconfig/network-scripts/ifcfg-ens33 #下面内容直接复制进去,如果有重复的可以去除 TYPE= ...

  4. C#-WebForm-Request、Response、QueryString

    知识点: Request - 获取请求对象 专门用来接传递过来的值 Request["key"](李献策lxc) 1.获取地址栏传递过来的值 get 2.获取表单传递过来的参数值 ...

  5. lspci

    lspci 是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具. 列出所有的PCIE设备: lspci 选项: -v 使得 lspci 以冗余模式显示所有设备的详细信息. -vv ...

  6. 阿里云 下载的 apache 证书 转换为 pcks8 证书

    第一步: 百度 搜索  rsa 转 pcks8 将 .key 文件 转换成 pcks8.key . 第二部: 将 chain.crt 的 内容 复制到 public.crt 下方.. 新的 publi ...

  7. js中的promise详解

    一 概述   Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件.ES6统一了用法,并原生提供了Promise对象.作为对象,Promise有一下两个特点: (1)对象的 ...

  8. 洛谷 P3757 [CQOI2017]老C的键盘

    题面 luogu 题解 其实就是一颗二叉树 我们假设左儿子小于根,右儿子大于根 考虑树形\(dp\) \(f[u][i]\)表示以\(u\)为根的子树,\(u\)为第\(i\)小 那么考虑子树合并 其 ...

  9. 在Azuer创建自己的Linux_VM

    ---恢复内容开始--- emm..就是想搭个自己的VPN去YouTube看看视屏找找资源什么的... (滑稽.jpg)然后发现似乎需要这个玩意儿 先去申请一个Azuer账户 然后根据要求一步步来就好 ...

  10. Mac下用Launchd实现使用rc.local执行开机启动命令

    其实原理很简单,使用Launchd创建一个开机启动的服务,然后这个服务关联/etc/rc.local文件,那么接下来操作rc.local就和Linux下一样的了. 当然,这种思路还可以直接使用在~/. ...