BZOJ 2028|SHOI 2009|会场预约|平衡树
来源:互联网 发布:欧陆风云4 mac 下载 编辑:程序博客网 时间:2024/06/06 13:57
【问题描述】A 大厦有一间空的礼堂,可以为企业或单位提供会议场所。这些会议中的大多
数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议
的时间申请不能冲突。也就是说,前一个会议结束日期必须在后一个会议的开始日期之前。
所以,如果要接受一个新的场地预约申请,就必须拒绝掉与这个申请相冲突的预约。
一般来说,如果 A 大夏方面事先已经接受了一个会场预约,例如从 10 日到 15 日,就不
会再接受与之相冲突的预约,例如从 12 日到 17 日。不过,有时出于经济利益,A 大夏方面
有时会接受一个新的会场预约,而拒绝掉一个甚至几个之前预定好的预约。
于是礼堂管理人员 Q 的笔记上经常记录着这样的信息:
本题中为方便起见,所有的日期都用一个数字表示。例如,如果一个为期 10 天的会议
从“90 日”到“99 日”,那么下一个会议最早只能在“100 日”开始。
最近,这个业务的工作量与日俱增,礼堂管理员 Q 希望参加 SGOI 的你替他设计一套计
算机系统来简化他的工作。这个系统只能执行下面两个操作:
A 操作:有一个新的预约是从“star 日”到“end 日”,并且拒绝所有与它相冲突的预
约。执行这个操作时候,你的系统应当返回为了这个新预约而拒绝掉的预约个数,以方便 Q
与自己的记录相核对。
B 操作:请你的系统返回当前的仍然有效的预约的总数。
【文件输入】输入文件:booking.in。第一行是一个整数 N,表示你的系统接受的操作总数。
接下去 N 行每行表示一个操作。每一行的格式为下面两者之一:“A star end”表示一个 A
操作;“B” 表示一个 B 操作。
【文件输出】输出文件:booking.out。输出有 N 行,每行依次对应一个输入。表示你的系
统对于该操作的返回值。
【输入输出样例】
booking.in
6
A 10 15
A 17 19
A 12 17
A 90 99
A 11 12
B
booking.out
0
0
2
0
1
2
【数据规模】
对于 10%的数据,N≤2500。
对于 60%的数据,N≤50000。
对于 100%的数据,N≤200000,1≤start,end≤100000。
水分姿势
考场上想了个
二分查找+树状数组
树状数组:维护1~k有多少线段端点。
二分查找:查找区间内的所有端点。
思路:对于每个查询A,有两种情况:
有线段部分覆盖区间,此时存在1或2端点在区间内,
二分查找利用树状数组找出这些端点,并删除。有线段全部覆盖区间,肯定只有1条覆盖此区间,
而且其左右端点最接近区间的左右端点(在区间外),
因此二分答案最接近区间的端点,判断是否跨越区间。
因此二分查找可以写成找最靠近查询右端点的点。。
这样情况2就可以找左半区间了。
需要另外开数组在端点处保存对应线段,
显然一个坐标只会存1个线段。
#include <cstdio>#include <cstring>#include <cstdlib>#include <map>#include <set>#include <vector>#include <queue>#include <algorithm>#define FOR(i,j,k) for(i=j;i<=k;++i)#define rep(i,j,k) for(i=j;i<k;++i)#define test printf("FUCK");#define ms(i,j) memset(i,j,sizeof(i))using namespace std;typedef long long ll;const int inf = 0x3f3f3f3f, mod = 1000000007;int read() { int s = 0, f = 1; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1; for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0'; return s * f;}int qpow(int a, int b) { int s = 1; for (; b; b /= 2, a = a * a % mod) if (b & 1) s = s * a % mod; return s;}void getmax(int &a, int b) { if (a < b) a = b; }void getmin(int &a, int b) { if (a > b) a = b; }namespace Solve { const int N = 200005; int c[N]; struct Seg { int l, r; } a[N]; void addPRIVATE(int i, int x) { for (; i <= 100000; i += i & -i) c[i] += x; } void add(const Seg &s, int x) { addPRIVATE(s.l, x); addPRIVATE(s.r, x); } int sum(int i) { int s = 0; for (; i; i -= i & -i) s += c[i]; return s; } int binary(int l, int r) { int base = sum(r), ans = -1; while (l <= r) { int mid = l + r >> 1, mm = sum(mid); if (mm == base && mm == sum(mid - 1)) r = mid - 1; else l = mid + 1, ans = mid; } return ans; } void solve() { int t = read(), tot = 0, l, r, x, del; char op[8]; while (t--) { scanf("%s", op); if (op[0] == 'A') { l = read(), r = read(); del = 0; // Case 1 while ((x = binary(l, r)) != -1) add(a[x], -1), ++del; // Case 2 x = binary(1, l - 1); if (x != -1 && a[x].l < l && a[x].r > r) add(a[x], -1), ++del; add(a[l] = a[r] = (Seg) { l, r }, 1); tot += 1 - del; printf("%d\n", del); } else printf("%d\n", tot); } }}#define FILENAME "booking"int main() { freopen(FILENAME".in","r",stdin); freopen(FILENAME".out","w",stdout); Solve::solve(); return 0;}
正确姿势
实际上从水分姿势中可以联想。。
我们一直要知道某个区间内有哪些点,最靠近区间边界的点是什么,那么set即可。。
好久没用过set,对set无感了。。以下程序为在线手打未测试正确性如有错误权当提供思路。
#include <cstdio>#include <set>using namespace std;struct Seg { int l, r; } a[100005];set<int> ss;int main() { int t, tot = 0, l, r, del; char op[8]; set<int>::iterator x; scanf("%d", &t); while (t--) { scanf("%s", op); if (op[0] == 'A') { scanf("%d%d", &l, &r); // Case 1 for (del = 0; ; ) { x = ss.lower_bound(l); if (x != ss.end() && *x <= r) ss.erase(a[*x].l), ss.erase(a[*x].r), ++del; else break; } // Case 2 x = ss.lower_bound(r + 1); if (x != ss.end() && a[*x].l < l && a[*x].r > r) ss.erase(a[*x].l), ss.erase(a[*x].r), ++del; a[l] = a[r] = (Seg) { l, r }; ss.insert(l); ss.insert(r); tot += 1 - del; printf("%d\n", del); } else printf("%d\n", tot); } return 0;}
经过实际测试(BZOJ)
水分方法 1.6s
set 1.2s
没有测试手写的。。
- BZOJ 2028|SHOI 2009|会场预约|平衡树
- |BZOJ 2028|平衡树|[SHOI2009]会场预约
- [树状数组]BZOJ 2028——[SHOI2009]会场预约
- SH0I 2009 会场预约
- 会场预约
- [SHOI2009] 会场预约
- BZOJ 1018|SHOI 2008|堵塞的交通|线段树
- P2161 [SHOI2009]Booking 会场预约
- P2161 [SHOI2009]Booking 会场预约
- bzoj2028 [SHOI2009]会场预约(set)
- 【洛谷 2161】 [Shoi2009]Booking 会场预约
- 洛谷P2161 [SHOI2009]Booking 会场预约
- [BZOJ2028][SHOI2009]会场预约(Splay)
- 【树状数组+二分】BZOJ2028 [SHOI2009]会场预约
- 洛谷P2161 [SHOI2009]Booking 会场预约_Splay
- BZOJ 2342 SHOI 2011 双倍回文 Manacher
- SHOI 2008 仙人掌图 BZOJ 1023
- 【BZOJ】【P3224】【普通平衡树】
- 【013】【内存调优】
- Maven+Spring+邮件发送
- mysql ICP和MRR性能优化测试
- WSGI接口
- CodeForces 9C Hexadecimal's Numbers(DFS)
- BZOJ 2028|SHOI 2009|会场预约|平衡树
- wincmd for windows
- Java的String char()[待补充]
- 联合体 union
- 【014】【JVM中的两个Survivor区】
- Qt播放WAV格式音频文件的两种方法
- [BZOJ4518][Sdoi2016]征途(斜率优化dp)
- 练习2————1015
- NYOJ 523 亡命逃窜(三维BFS)