POJ 3667 Hotel

题目链接

题意:有n个房间,如今有两个操作

1、找到连续长度a的空房间。入住,要尽量靠左边,假设有输出最左边的房间标号,假设没有输出0

2、清空[a, a + b - 1]的房间

思路:线段树的区间合并。记录下左边连续最长和右边连续最长空房间。和每一段的最大值。这样pushup的时候就是进行区间合并,注意查询的时候因为是要尽量左,所以先查左孩子,在查横跨左右的,在查右孩子

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2) const int N = 50005; int n, m; struct Node {
int l, r, lsum, rsum, sum, sumv, lazy;
int size() {return r - l + 1;}
void gao(int v) {
lazy = v;
if (v) lsum = rsum = sum = 0;
else lsum = rsum = sum = r - l + 1;
sumv = l;
}
} node[N * 4]; void pushup(int x) {
if (node[lson(x)].lsum == node[lson(x)].size()) node[x].lsum = node[lson(x)].lsum + node[rson(x)].lsum;
else node[x].lsum = node[lson(x)].lsum;
if (node[rson(x)].rsum == node[rson(x)].size()) node[x].rsum = node[lson(x)].rsum + node[rson(x)].rsum;
else node[x].rsum = node[rson(x)].rsum;
node[x].sum = node[lson(x)].sum;
node[x].sumv = node[lson(x)].sumv;
if (node[x].sum < node[lson(x)].rsum + node[rson(x)].lsum) {
node[x].sum = node[lson(x)].rsum + node[rson(x)].lsum;
node[x].sumv = node[lson(x)].r - node[lson(x)].rsum + 1;
}
if (node[x].sum < node[rson(x)].sum) {
node[x].sum = node[rson(x)].sum;
node[x].sumv = node[rson(x)].sumv;
}
} void pushdown(int x) {
if (node[x].lazy != -1) {
node[lson(x)].gao(node[x].lazy);
node[rson(x)].gao(node[x].lazy);
node[x].lazy = -1;
}
} void build(int l, int r, int x = 0) {
node[x].l = l; node[x].r = r; node[x].lazy = -1;
if (l == r) {
node[x].lsum = node[x].rsum = node[x].sum = 1;
return;
}
int mid = (l + r) / 2;
build(l, mid, lson(x));
build(mid + 1, r, rson(x));
pushup(x);
} void add(int l, int r, int v, int x = 0) {
if (node[x].l >= l && node[x].r <= r) {
node[x].gao(v);
return;
}
int mid = (node[x].l + node[x].r) / 2;
pushdown(x);
if (l <= mid) add(l, r, v, lson(x));
if (r > mid) add(l, r, v, rson(x));
pushup(x);
} int query(int v, int x = 0) {
if (node[x].l == node[x].r) {
if (node[x].sum >= v) return node[x].sumv;
return 0;
}
pushdown(x);
int ans = 0;
if (node[lson(x)].sum >= v)
ans = query(v, lson(x));
else if (node[lson(x)].rsum + node[rson(x)].lsum >= v) ans = node[lson(x)].r - node[lson(x)].rsum + 1;
else if (node[rson(x)].sum >= v)
ans = query(v, rson(x));
pushup(x);
return ans;
} int main() {
while (~scanf("%d%d", &n, &m)) {
build(1, n);
int op, a, b;
while (m--) {
scanf("%d%d", &op, &a);
if (op == 2) {
scanf("%d", &b);
add(a, a + b - 1, 0);
} else {
int tmp = query(a);
printf("%d\n", tmp);
if (tmp == 0) continue;
add(tmp, tmp + a - 1, 1);
}
}
}
return 0;
}

POJ 3667 Hotel(线段树)的更多相关文章

  1. poj 3667 Hotel (线段树)

    http://poj.org/problem?id=3667 Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 94 ...

  2. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  3. POJ 3667 Hotel (线段树区间合并)

    题目链接:http://poj.org/problem?id=3667 最初给你n间空房,m个操作: 操作1 a 表示检查是否有连续的a间空房,输出最左边的空房编号,并入住a间房间. 操作2 a b ...

  4. poj 3667 Hotel(线段树,区间合并)

    Hotel Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 10858Accepted: 4691 Description The ...

  5. PKU 3667 Hotel(线段树)

    Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

  6. POJ 1823 Hotel 线段树

    题目链接 线段树的区间合并. 和上一题差不多....第三种操作只需要输出maxx[1]的值就可以. #include <iostream> #include <vector> ...

  7. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  8. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

  9. [USACO08FEB]酒店Hotel 线段树

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

随机推荐

  1. POJ 3087 Shuffle'm Up【模拟/map/string】

    Shuffle'm Up Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14471 Accepted: 6633 Descrip ...

  2. 【DFS序】【线段树】bzoj4034 [HAOI2015]T2

    分开维护树的入栈序和出栈序,用两棵线段树.回答时就是用一颗的减去另一棵的. #include<cstdio> #include<algorithm> using namespa ...

  3. 【后缀数组】poj3581 Sequence

    考虑第一次切割,必然切割的是翻转后字典序最小的前缀,伪证: 若切割位置更靠前:则会导致第一个数翻转后更靠前,字典序必然更大. 若切割位置更靠后,则显然也会导致字典序更大. ↑,sa即可 对于第二次切割 ...

  4. 【进制转换】codevs 1474 十进制转m进制

    #include<cstdio> using namespace std; ],en; int main() { scanf("%d%d",&n,&m) ...

  5. 【斜率优化】BZOJ1096-[ZJOI2007]仓库建设

    [题目大意] 有n个工厂编号分别为1-n,第i个仓库库存量为p[i],距离第1个仓库的距离为x[i](x[1]=0).在每一个工厂建立一个仓库费用为c[i],没有建立仓库的工厂只能往编号大于它的仓库运 ...

  6. ListView(下)自定义适配器

    (一) 1.效果图 2.activity_main.xml <?xml version="1.0" encoding="utf-8"?> <L ...

  7. iOS开发 Swift开发数独游戏(五)显示游戏答案

          要点是设置好Tag就好,通过代码找到并初始化即可. 1: // 2: // ShowAnswerController.swift 3: // sudoku-v02 4: // 5: // ...

  8. Linux下的/etc/crontab文件和crontab -e命令区别及Crontab命令详解(转)

    /etc/crontab文件和crontab -e命令区别 1.格式不同 前者 # For details see crontabs # Example of job definition: # .- ...

  9. 学习Microsoft SQL Server 2008技术内幕:T-SQL语法基础

    第 2 章: 单表查询 use TSQLFundamentals2008; select * from Sales.orders; select empid, year(orderdate) as o ...

  10. SQL Server Latch Classes Library

    https://www.sqlskills.com/help/latches/ (Companion SQL Server Wait Types Library) This site lists al ...