[USACO08FEB]酒店Hotel
这道题以前在学校内网刷过类似的,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的更多相关文章
- 洛谷P2894 [USACO08FEB]酒店Hotel
P2894 [USACO08FEB]酒店Hotel https://www.luogu.org/problem/show?pid=2894 题目描述 The cows are journeying n ...
- 线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel
题面:P2894 [USACO08FEB]酒店Hotel 题解:和基础的线段树操作差别不是很大,就是在传统的线段树基础上多维护一段区间最长的合法前驱(h_),最长合法后驱(t_),一段中最长的合法区间 ...
- P2894 [USACO08FEB]酒店Hotel
P2894 [USACO08FEB]酒店Hotel 简单的线段树维护区间信息. 维护三个值,一个是从左端点能拓展的长度,一个是从右端点能脱产的的长度.另一个是整个区间内的最大连续零一长度. 记录这三个 ...
- 洛谷 P2894 [USACO08FEB]酒店Hotel 解题报告
P2894 [USACO08FEB]酒店Hotel 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultur ...
- 线段树【洛谷P2894】 [USACO08FEB]酒店Hotel
P2894 [USACO08FEB]酒店Hotel 参考样例,第一行输入n,m ,n代表有n个房间,编号为1---n,开始都为空房,m表示以下有m行操作,以下 每行先输入一个数 i ,表示一种操作: ...
- 浅谈线段树 (例题:[USACO08FEB]酒店Hotel)By cellur925
今天我们说说线段树. 我个人还是非常欣赏这种数据结构的.(逃)因为它足够优美,有递归结构,有左子树和右子树,还有二分的思想. emm这个文章打算自用,就不写那些基本的操作了... 1° 简单的懒标记( ...
- [USACO08FEB]酒店Hotel 线段树
[USACO08FEB]酒店Hotel 线段树 题面 其实就是区间多维护一个lmax,rmax(表示从左开始有连续lmax个空房,一直有连续rmax个空房到最右边),合并时讨论一下即可. void p ...
- 洛谷P2894 [USACO08FEB]酒店Hotel [线段树]
题目传送门 酒店 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and ...
- [USACO08FEB]酒店Hotel 线段树 BZOJ 1593
题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...
- luogu P2894 [USACO08FEB]酒店Hotel
题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...
随机推荐
- Windows Server 2008 R2系统上安装SQLServer2012集群(简略)
4台服务器(1台AD.2台SQL服务器.1台iSCSI存储服务器) 9个IP(1个AD的IP.2个SQL服务器的IP.2个心跳IP.1个iSCSI存储服务器的IP.1个集群IP.1个DTC的IP.1个 ...
- 理解Xaml标记语言
理解XAML XAML基于XAML,因而具有与XAML相似的特性.在XAMl中,同样必须区分大小写,但是Xaml以.xaml作为扩展名,表示这是一个应用程序的标记扩展文件.WPF中的XAML主要用于创 ...
- JavaScript - 表单提交前预览图片
其实这东西网上到处都是,但并不完整. 正好我也遇到了这个问题,不仅仅是预览,还需要得到图片的属性. 于是东凑西凑整理出一个完整的版本,并根据个人的理解加上了一点点说明. 首先做一些准备工作,HTML方 ...
- springboot自定义异常
SpringBoot自定义异常以及异常处理 在web项目中,我们可能需要给前端返回不同的提示码.例如:401表示没有权限,500代表位置异常,200代表请求成功等.但是这些提示码远远不能满足我们返回给 ...
- JS之捕获冒泡和事件委托
一.事件流(捕获,冒泡) 事件流:指从页面中接收事件的顺序,有冒泡流和捕获流. 当页面中发生某种事件(比如鼠标点击,鼠标滑过等)时,毫无疑问子元素和父元素都会接收到该事件,可具体顺序是怎样的呢?冒 ...
- select获取选中项的值与文本
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- VScode设置jsx语法自动补全
1.打开VScode 2.文件>首选项>设置 3.加上以下配置项就可以了 "emmet.includeLanguages": { "javascript&qu ...
- Unity使Text 文字逐个出现
Text tex; string s="Unity使Text 文字逐个出现"; //字符出现间隔 waitTime = 0.3f; // float speed=0; //方法一 ...
- Vue2.0中的Ajax请求
Vue可以借助于vue-resource来实现Ajax请求 http请求报文 浏览器与服务器数据交互是遵循http协议的,当浏览器要访问服务器的时候,浏览器需要将相关请求数据提交给服务器. 格式分为: ...
- android之键盘转载
显示键盘: EditText editText.setFocusable(true); editText.setFocusableInTouchMode(true); editText.request ...