[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 ...
随机推荐
- window.history,页面中的返回按钮
一.页面中的返回按钮事件 window.history可以不加window这个前缀 他的方法有: window.history.go(-1); //-n表示后退n页,n表示前进n页,或者是一个url ...
- JS的Object类的属性、方法及如何创建对象
属性 constructor:对创建对象的函数的引用(指针).对于Object类,该指针指向原始的object()函数. prototype:对该对象的对象原型的引用.对于所有的类,它默认返回Obje ...
- Navicat 连接MySQL 8.0.11 出现2059错误
错误 使用Navicat Premium 连接MySQL时出现如下错误: 原因 mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是cach ...
- Boxlayout中button改变大小
需要先设置maximunsize neuStart.setBorder(BorderFactory.createRaisedBevelBorder()); neuStart.setMaximumSiz ...
- mysql根据时间查询日期的优化
例如查询昨日新注册用户,写法有如下两种: EXPLAIN select * from chess_user u where DATE_FORMAT(u.register_time,'%Y-%m-%d' ...
- MySql数据快速导入
使用LOAD DATA INFILE 插入速度可以提升很多 左侧是直接导入100W花费135s ,Dos界面通过Load方式导入450W只用时23s,性能一下子显示出来了.
- html简介(自己理解和老师讲课)
首先讲开发网页三种技术:html,css,javascript.html负责网页的结构,css站在没学角度对网页进行美化,javascript负责网页交互,站在用户体验角度设计网页交互效果 而我们所学 ...
- 使用dojo.connect()添加事件的注意事项
使用dojo.connect()添加事件处理器是很方便的,不用再考虑跨浏览器的问题了.但要想正确地使用这个方法,仍然要注意几个问题: 1.用dojo.byId()获取的是dom元素,而用 ...
- 07_Redis事务
[简述] 事务是指一系列的操作步骤,着一些列的操作步骤,要么完全地执行,要不完全地不执行. 比如微博中: A用户关注了B用户,那么A的关注列表里就会有B用户,B用户的粉丝列表里就会有A用户. 这个关注 ...
- _itoa atoi、atof、itoa、itow _itoa_s 类型转换使用说明
原文:http://www.cnblogs.com/lidabo/archive/2012/07/10/2584706.html _itoa 功能:把一整数转换为字符串 用法:char * _itoa ...