[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 ...
随机推荐
- [APIO2018] Circle selection 选圆圈
Description 给出 \(n\) 个圆 \((x_i,y_i,r_i)\) 每次重复以下步骤: 找出半径最大的圆,并删除与这个圆相交的圆 求出每一个圆是被哪个圆删除的 Solution \(k ...
- PHP学习4——面向对象
主要内容: 创建类 成员方法 构造方法 析构方法 封装 继承 接口 多态 静态成员 常用关键字 常用魔术方法 从PHP5开始引入了面向对象的全部机制,面向对象的特性符合软件工程的3个目标:重用性,灵活 ...
- Eclipse 工具栏无法移动的解决办法
升级到Juno后发现工具栏有些乱 而且无法拖动,试了下http://blog.csdn.net/cxx504659987/article/details/38532599的方法 发现配置文件里没有文中 ...
- idea快捷键、常用设置
代码提示: code completion :ALT + / 选用Eclipse的keymap. 设置代码助手快捷键(keymap-basic) 代码上下行复制(Ctrl + Alt + Down ...
- Java温故而知新(7)Object类及其方法讲解
一.java.lang.Object java.lang包在使用的时候无需显示导入,编译时由编译器自动导入. Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类. Object类 ...
- Heka 的编译
Heka是Mozilla开源的,基于Go语言实现的,插件式log收集和分析系统. 已经编译好的 release 版本可以在下面地址下载: https://github.com/mozilla-serv ...
- express的proxy实现前后端分离
var express = require('express') var proxy = require('http-proxy-middleware') var app = express() ap ...
- 移动web开发都会遇到的坑(会持续更新)
1.自适应第一招 <meta name="viewport" content="width=device-width,initial-scale=1.0,user- ...
- COGS 有标号的二分图计数系列
其实这三道题都是不错的……(虽然感觉第三题略套路了……) 分别写一下做法好了…… COGS2392 有标号的二分图计数 I 这个就很简单了,Noip难度. 显然可以直接认为黑点和白点分别位于二分图两侧 ...
- 解决方案看起来是受源代码管理,但无法找到它的绑定信息。保存解决方案的源代码管理设置的MSSCCPRJ.SCC文件或其他项可能己被删除。
Visual Studio 2015 + SVN 开发环境,今天打开项目,就报了下面这个错误,先前是好好的! 解决方案看起来是受源代码管理,但无法找到它的绑定信息.保存解决方案的源代码管理设置的MSS ...