首页 > 其他分享 >Luogu 2894 酒店Hotel

Luogu 2894 酒店Hotel

时间:2022-10-25 17:04:42浏览次数:77  
标签:int Luogu Hotel tree else 2894 区间 长度 include


题目链接:​​传送门​

题目描述:

参考样例,第一行输入n(1 ≤ n ≤ 50,000),m(1 ≤ M < 50,000) ,n代表有n个房间,编号为1—n,开始都为空房,m表示以下有m行操作,以下 每行先输入一个数 i ,表示一种操作:
若i为1,表示查询房间,再输入一个数x,表示在1–n 房间中找到长度为x的连续空房,输出连续x个房间中左端的房间号,尽量让这个房间号最小,若找不到长度为x的连续空房,输出0。
若i为2,表示退房,再输入两个数 x,y 代表 房间号 x—x+y-1 退房,即让房间为空。

输入样例

10 6
1 3
1 3
1 3
1 3
2 5 5
1 6

输出样例

1
4
7
0
5

这算是对线段树的理解的考察吧
我们考虑维护
我们维护区间长度(
左右端点(
一个标记表示是开房还是退房(
这个区间内的最长0的个数(
这个区间从左端点开始最长0的个数(
这个区间从右端点开始最长0的个数(
在下传标记的时候就可以维护了
具体怎么样维护在代码里说

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <vector>
#include <iomanip>
#define
#define
#define

using namespace std;
struct node {
int l, r, w, lt, rt, t, f; //各个维护的值
}tree[A];
int n, m, x, y, typ, ans;
void up(int k) {
tree[k].t = max(tree[k << 1].rt + tree[k << 1 | 1].lt, max(tree[k << 1].t, tree[k << 1 | 1].t));
//当前区间最长的一段可以是左儿子的右边开始最长区间长度加上左儿子的左边开始最长区间长度
//还可以是左儿子的区间最长长度或右儿子的区间最长长度
if (tree[k << 1].lt == tree[k << 1].w) tree[k].lt = tree[k << 1].lt + tree[k << 1 | 1].lt;
//可以是左儿子的区间长度加上右儿子的左边开始最长区间长度
else tree[k].lt = tree[k << 1].lt;
if (tree[k << 1 | 1].rt == tree[k << 1 | 1].w) tree[k].rt = tree[k << 1].rt + tree[k << 1 | 1].rt;
//可以是右儿子的区间长度加上左儿子的右边开始最长区间长度
//想一想,这两块可以并到一起
else tree[k].rt = tree[k << 1 | 1].rt;
}
void build(int k, int l, int r) {
tree[k].l = l; tree[k].r = r; tree[k].w = r - l + 1; //w维护这段区间的长度
if (l == r) {
tree[k].lt = tree[k].rt = tree[k].t = 1; //初值当然都为1
return;
}
int m = (l + r) >> 1;
build(k << 1, l, m);
build(k << 1 | 1, m + 1, r);
up(k);
}
void down(int k) { //标记下传
if (tree[k].f == 1) {
tree[k << 1].lt = tree[k << 1].rt = tree[k << 1].t = 0; tree[k << 1].f = 1;
tree[k << 1 | 1].lt = tree[k << 1 | 1].rt = tree[k << 1 | 1].t = 0; tree[k << 1 | 1].f = 1; tree[k].f = 0;
//这是删除点,也就是退房
}
if (tree[k].f == 2) {
tree[k << 1].lt = tree[k << 1].rt = tree[k << 1].t = tree[k << 1].w; tree[k << 1].f = 2;
tree[k << 1 | 1].lt = tree[k << 1 | 1].rt = tree[k << 1 | 1].t = tree[k << 1 | 1].w; tree[k << 1 | 1].f = 2; tree[k].f = 0;
//开房
}
}
void change(int k, int l, int r, int typ) {
if (l <= tree[k].l and r >= tree[k].r) {
if (typ == 1) {
tree[k].lt = tree[k].rt = tree[k].t = 0;
tree[k].f = 1;
//退房
}
else tree[k].lt = tree[k].rt = tree[k].t = tree[k].w, tree[k].f = 2;//开房
return;
}
down(k);
int m = (tree[k].l + tree[k].r) >> 1;
if (l <= m) change(k << 1, l, r, typ);
if (r > m) change(k << 1 | 1, l, r, typ);
up(k);
}
void ask(int k) {
//可能大多数人会觉得这里有判断是否在区间内的操作
//但这里的操作区间是1-n,所以就没有必要判断了
//直接下放标记
down(k);
if (tree[k << 1].t >= x) ask(k << 1); //向左儿子找
else if (tree[k << 1].rt + tree[k << 1 | 1].lt >= x) ans = tree[k << 1].r - tree[k << 1].rt + 1;
//两端区间并起来能达到题目要求
//也就是明确了区间端点
//到这里就可以返回答案了
//就按题目要求返回左端点的编号
else if (tree[k << 1 | 1].t >= x) ask(k << 1 | 1); //向右儿子找
up(k);
}

int main() {
scanf("%d%d", &n, &m);
build(1, 1, n);
while (m--) {
scanf("%d", &typ);
if (typ == 1) {
scanf("%d", &x);
if (tree[1].t < x) puts("0");
else {
ans = 0;
ask(1); //习惯写不带返回值的函数
printf("%d\n", ans);
change(1, ans, ans + x - 1, 1); //要求查完之后把房开开
}
}
else {
scanf("%d%d", &x, &y);
change(1, x, x + y - 1, 2); //退房
}
}
return 0;
}


标签:int,Luogu,Hotel,tree,else,2894,区间,长度,include
From: https://blog.51cto.com/lyle/5794949

相关文章

  • Luogu 3478 [POI2008]STA-Station
    题目链接:​​传送门​​题目描述给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大输入样例814564567682434输出样例7一句话题意好......
  • Luogu 1507 NASA的食物计划
    题目链接:​​传送门​​题目背景NASA(美国航空航天局)因为航天飞机的隔热瓦等其他安全技术问题一直大伤脑筋,因此在各方压力下终止了航天飞机的历史,但是此类事情会不会在以......
  • Luogu 1853 投资的最大效益
    题目链接:​​传送门​​题目背景约翰先生获得了一大笔遗产,他暂时还用不上这一笔钱,他决定进行投资以获得更大的效益。银行工作人员向他提供了多种债券,每一种债券都能在固定的......
  • Luogu 1833 樱花
    题目链接:​​传送门​​题目背景《爱与愁的故事第四弹·plant》第一章。题目描述爱与愁大神后院里种了n棵樱花树,每棵都有美学值Ci。爱与愁大神在每天上学前都会来赏花。爱与......
  • Luogu 2014 选课
    题目链接:​​传送门​​题目描述在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程......
  • Luogu P4171 [JSOI2010]满汉全席
    题目链接:​​传送门​​2-sat板子题注意输入的时候可不要以为w和h后面数字只有一位*/#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#includ......
  • Luogu P4915 帕秋莉的魔导书
    题目链接:​​传送门​​动态开点是真的麻烦跟普通线段树差别还是挺大的题意就是区间前缀和的和除以区间长度#include<iostream>#include<cstdio>#include<cstring>#inc......
  • Luogu P4868 Preprefix sum
    题目链接:​​传送门​​线段树维护前缀和简单明了修改就修改当然还有更快的树状数组差分的做法*/#include<iostream>#include<cstdio>#include<cstring>#include<cs......
  • Luogu P4514 上帝造题的七分钟
    题目链接:​​传送门​​二维树状数组区间加区间求和烦人的输入#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<complex>#include<......
  • Luogu P2455 [SDOI2006]线性方程组
    题目链接:​​传送门​​高斯消元可以去下面看一下​​​https://www.bilibili.com/video/av4688674​​​听视频比瞅博客有用得多这题算比较标准的板子了各种情况都有......