POJ 3667 Hotel(线段树区间合并)
来源:互联网 发布:征服者rd88升级软件 编辑:程序博客网 时间:2024/06/06 11:39
题意:
一家旅馆有N(1 ≤ N ≤ 50000)间房间,并且所有的房间都是连续排列在同一边,现在每个观光团需要入住房间,要求房间的编号为连续的
r...r+Di−1 ,并且r是最小的;
参观者同样可能退房,并且他们每次退房都是编号为Xi...Xi+Di−1 (1≤Xi≤N−Di+1) 的房间。
现在有两种操作:
1. 1 a 每个观光团需要入住a间编号连续的房间
2. 2 a b 观光者需要退房间,其中房间编号是a...a+b−1
要求对于每次询问,输出为观光团分配数目为a的房间中编号最小的房间编号
解析:
利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是答案,同时因为需要求出连续区间的最大长度,因此每次pushUp时都将左右区间合并,
lsum 维护左区间的最大长度,
rsum 维护右区间的最大长度,
msum 维护区间1...N 中的最大连续区间长度,
cover 标志对应区间是否为空。
#include <cstdio>#include <cstring>#include <algorithm>#define ls o<<1#define rs o<<1|1#define lson ls, L, M#define rson rs, M+1, Rusing namespace std;const int N = 50005;int cover[N<<2]; //懒惰标记 -1无操作,0区间为空,1区间为满int lsum[N<<2], rsum[N<<2], msum[N<<2];int n, m;void pushDown(int o, int L, int R) { if(cover[o] != -1) { int M = (L + R)/2; cover[ls] = cover[rs] = cover[o]; lsum[ls] = rsum[ls] = msum[ls] = cover[o] ? 0 : (M - L + 1); lsum[rs] = rsum[rs] = msum[rs] = cover[o] ? 0 : (R - M); cover[o] = -1; }}void pushUp(int o, int L, int R) { int M = (L + R)/2; int len1 = M - L + 1, len2 = R - M; lsum[o] = lsum[ls]; rsum[o] = rsum[rs]; if(lsum[o] == len1) lsum[o] += lsum[rs]; if(rsum[o] == len2) rsum[o] += rsum[ls]; msum[o] = max(msum[ls], max(msum[rs], rsum[ls] + lsum[rs])); if(cover[ls] == cover[rs]) cover[o] = cover[ls]; else cover[o] = -1;}void modify(int o, int L, int R, int ql, int qr, int val) { if(ql <= L && R <= qr) { cover[o] = val; lsum[o] = rsum[o] = msum[o] = (val) ? 0 : (R-L+1); return ; } pushDown(o, L, R); int M = (L + R)/2; if(ql <= M) modify(lson, ql, qr, val); if(qr > M) modify(rson, ql, qr, val); pushUp(o, L, R);}int query(int o, int L, int R, int need) { if(L == R) return L; pushDown(o, L, R); int M = (L + R)/2; if(msum[ls] >= need) return query(lson, need); else if(lsum[rs] + rsum[ls] >= need) return M - rsum[ls] + 1; else return query(rson, need);}void build(int o, int L, int R) { cover[o] = -1; lsum[o] = rsum[o] = msum[o] = R - L + 1; if(L == R) return ; int M = (L + R)/2; build(lson); build(rson);}int main() { while(scanf("%d%d", &n, &m) != EOF) { build(1, 1, n); int oper, ql, qr, need; while(m--) { scanf("%d", &oper); if(oper == 1) { scanf("%d", &need); if(msum[1] < need) { puts("0"); continue; } ql = query(1, 1, n, need); printf("%d\n", ql); qr = ql + need - 1; modify(1, 1, n, ql, qr, 1); }else { scanf("%d%d", &ql, &need); qr = ql + need - 1; modify(1, 1, n, ql, qr, 0); } } } return 0;}
0 0
- POJ 3667 Hotel 线段树区间合并
- poj 3667 Hotel 线段树区间合并
- POJ 3667 Hotel 线段树 区间合并
- Poj 3667 Hotel 线段树 区间合并
- POJ 3667-hotel(线段树区间合并)
- POJ 3667 Hotel. (线段树 区间合并)
- 【线段树】POJ 3667 Hotel 区间合并
- POJ 3667 Hotel ( 线段树区间合并 )
- 线段树 区间合并 poj 3667 Hotel
- POJ 3667 Hotel 线段树 区间合并
- POJ - 3667 Hotel (线段树 + 区间合并)
- POJ 3667 Hotel 【线段树 区间合并】
- poj 3667 Hotel 【线段树区间合并】
- POJ 3667Hotel 线段树区间合并
- POJ 3667 - Hotel(线段树+区间合并)
- poj 3667 Hotel 线段树区间合并
- poj 3667 hotel (线段树+区间合并)
- POJ 3667 Hotel 区间合并+线段树 *
- linux Oops和Panic关系 .
- Django安装及操作(windows)
- 输入两颗二叉树A,B,判断B是不是A的子结构。(树中可能有重复的值)
- android 用shape oval属性画圆环变成黑圆形解决办法
- CSS3变形属性:CSS33DTransform
- POJ 3667 Hotel(线段树区间合并)
- 相爱相杀:程序员的数学
- [leetcode]51 Delete Node in a Linked List
- 如果获取apk的总方法数
- LINUX重启MYSQL的命令
- [unity3d]手游资源热更新策略探讨
- C# 抽象类和抽象方法详解
- 面试题二叉树相关问题总结
- Linux 中open系统调用实现原理 2012-11-29 23:03:48 http://blog.chinaunix.net/uid-25968088-id-3426026.html