嘟嘟嘟

这道题以前在学校内网刷过类似的,AC了后还挺有成就感,所以更详细的题解请看这里

总的来说,就是用线段树维护区间最长连续0.因此我们要维护这么几个值:lmax:从当前区间左端点开始最长的连续0的长度;rmax:右端点开始最长连续0的长度;imax当前区间最长连续0的长度。有了这三个量,区间就可以合并了。

合并的方法看上面的链接,这里不再细讲了,这道题主要的区别查询。

查询是找长度为x的区间的位置,而不是在给定区间中查询最长连续区间。查询的具体步骤是这样的:

1.当前区间连续的最长长度比要找的len小,自然返回0。

2.否则我们看lmax[now],这个区间左起最长长度,如果大于len,就返回左端点就行啦。

3.因为题中说要使房间号尽量小,所以接下来应该看rmax[now << 1] + lmax[now << 1 |1]和len的关系,如果包含len,就返回r[now << 1] - rmax[now << 1] + 1.

4.最后就只能递归找右子区间了。

就因为上面的逻辑我刚开始想的不对,于是debug了快一个下午……

emacs格式,代码缩进很丑

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 5e4 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), las = ' ';
while(!isdigit(ch)) las = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << ) + (ans << ) + ch - '', ch = getchar();
if(las == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
} int n, m; struct Tree
{
int l, r, lzy;
int lmax, rmax, imax;
Tree operator + (const Tree& other)const
{
Tree ret;
ret.l = l; ret.r = other.r;
ret.lzy = -;
ret.lmax = lmax;
if(lmax == r - l + ) ret.lmax += other.lmax;
ret.rmax = other.rmax;
if(other.rmax == other.r - other.l + ) ret.rmax += rmax;
ret.imax = max(max(imax, other.imax), rmax + other.lmax);
return ret;
}
}t[maxn << ];
void build(int L, int R, int now)
{
t[now].l = L; t[now].r = R;
t[now].lzy = -;
t[now].lmax = t[now].rmax = t[now].imax = R - L + ;
if(L == R) return;
int mid = (L + R) >> ;
build(L, mid, now << );
build(mid + , R, now << | );
}
void pushdown(int now)
{
if(t[now].lzy != -)
{
t[now << ].lmax = t[now << ].rmax = t[now << ].imax = (t[now << ].r - t[now << ].l + ) * (t[now].lzy ^ );
t[now << | ].lmax = t[now << | ].rmax = t[now << | ].imax = (t[now << | ].r - t[now << | ].l + ) * (t[now].lzy ^ );
t[now << ].lzy = t[now << | ].lzy = t[now].lzy;
t[now].lzy = -;
}
}
void update(int L, int R, int now, int flg)
{
if(L == t[now].l && R == t[now].r)
{
t[now].lmax = t[now].rmax = t[now].imax = (R - L + ) * (flg ^ );
t[now].lzy = flg; return;
}
pushdown(now);
int mid = (t[now].l + t[now].r) >> ;
if(R <= mid) update(L, R, now << , flg);
else if(L > mid) update(L, R, now << | , flg);
else update(L, mid, now << , flg), update(mid + , R, now << | , flg);
t[now] = t[now << ] + t[now << | ];
}
int query(int len, int now)
{
if(t[now].imax < len) return ;
pushdown(now);
if(t[now].lmax >= len) return t[now].l;
else if(t[now << ].imax >= len) return query(len, now << );
else if(t[now << ].rmax + t[now << | ].lmax >= len) return t[now << ].r - t[now << ].rmax + ;
else return query(len, now << | );
} int main()
{
n = read(); m = read();
build(, n, );
for(int i = ; i <= m; ++i)
{
int d = read();
if(d == )
{
int x = read();
int ans = query(x, );
write(ans); enter;
if(ans) update(ans, ans + x - , , );
}
else
{
int L = read(), len = read();
update(L, L + len - , , );
}
}
return ;
}

[USACO08FEB]酒店Hotel的更多相关文章

  1. 洛谷P2894 [USACO08FEB]酒店Hotel

    P2894 [USACO08FEB]酒店Hotel https://www.luogu.org/problem/show?pid=2894 题目描述 The cows are journeying n ...

  2. 线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel

    题面:P2894 [USACO08FEB]酒店Hotel 题解:和基础的线段树操作差别不是很大,就是在传统的线段树基础上多维护一段区间最长的合法前驱(h_),最长合法后驱(t_),一段中最长的合法区间 ...

  3. P2894 [USACO08FEB]酒店Hotel

    P2894 [USACO08FEB]酒店Hotel 简单的线段树维护区间信息. 维护三个值,一个是从左端点能拓展的长度,一个是从右端点能脱产的的长度.另一个是整个区间内的最大连续零一长度. 记录这三个 ...

  4. 洛谷 P2894 [USACO08FEB]酒店Hotel 解题报告

    P2894 [USACO08FEB]酒店Hotel 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultur ...

  5. 线段树【洛谷P2894】 [USACO08FEB]酒店Hotel

    P2894 [USACO08FEB]酒店Hotel 参考样例,第一行输入n,m ,n代表有n个房间,编号为1---n,开始都为空房,m表示以下有m行操作,以下 每行先输入一个数 i ,表示一种操作: ...

  6. 浅谈线段树 (例题:[USACO08FEB]酒店Hotel)By cellur925

    今天我们说说线段树. 我个人还是非常欣赏这种数据结构的.(逃)因为它足够优美,有递归结构,有左子树和右子树,还有二分的思想. emm这个文章打算自用,就不写那些基本的操作了... 1° 简单的懒标记( ...

  7. [USACO08FEB]酒店Hotel 线段树

    [USACO08FEB]酒店Hotel 线段树 题面 其实就是区间多维护一个lmax,rmax(表示从左开始有连续lmax个空房,一直有连续rmax个空房到最右边),合并时讨论一下即可. void p ...

  8. 洛谷P2894 [USACO08FEB]酒店Hotel [线段树]

    题目传送门 酒店 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and ...

  9. [USACO08FEB]酒店Hotel 线段树 BZOJ 1593

    题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

  10. luogu P2894 [USACO08FEB]酒店Hotel

    题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

随机推荐

  1. [转]NLog 自定义字段 写入 oracle

    本文转自:http://www.cnblogs.com/skyapplezhao/p/5690695.html 1.通过Nuget安装NLog 下载,简单入门 请参照 我刚才转的几篇文章,下面我直接贴 ...

  2. jQuery插件 -- UI插件Tabs Widget 1.10

    最近将tabs(标签页)整合到Admin LTE( 一个完全响应式管理模板,基于Bootstrap3的框架.)中使用.过程中走了不少弯路,原因是没有注意版本问题,jquery ui tabs 每次升级 ...

  3. HTML <a>标签的使用

    <a></a>标签称作链接标记,由<a>与</a>所围的文字.图片等可以作为一个链接 Eg:<a href="index.html&qu ...

  4. ​Error -4075: File not found. An error occurred merging module <MODULENAME> for feature <FEATURENAME>.

    利用Install Shield2010制作安装包的时候一直报这样的错误,原以为是我自己安装包制作流程的问题,又重新做了2个,但是还是出现问题. 解决办法: 查找资料发现是Install Shield ...

  5. golang学习之go简单博客应用

    先说说golang的语法吧,个人觉得有以下特点: 简洁,不管是变量.方法声明,还是代码编写,均十分简洁,效率也比较高 非纯粹面向对象,但是go的struct类似c的struct,go的结构体还可以进行 ...

  6. servlet开发(四)之ServletContext

    接上一篇. 2.3.4 利用ServletContext对象读取资源文件 比如我们要读取web项目中的配置文件. 项目目录结构如下: 使用ServletContext对象读取资源文件的示例代码如下: ...

  7. Bazaar 版本控制工具

    Bazaar是一个分布式的版本控制系统,它发布在GPL许可协议之下,并可用于Windows.GNU/Linux.UNIX以及Mac OS系统.Bazaar由Canonical公司赞助,目前已服务于Sa ...

  8. 四层协议和Socket编程

    <四层协议图> <Soclet编程模型图>

  9. ZT 为什么Java中继承多数是有害的?

    大多数好的设计者象躲避瘟疫一样来避免使用实现继承(extends 关系).实际上80%的代码应该完全用interfaces写,而不是通过extends.“Java设计模式”一书详细阐述了怎样用接口继承 ...

  10. 第5章 css与背景相关的样式background

    background-origin 设置元素背景图片的原始起始位置. 语法: background-origin : border-box | padding-box | content-box; 参 ...