题目描述

PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地。这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突。也就是说,前一个会议的结束日期必须在后一个会议的开始日期之前。所以,如果要接受一个新的场地预约申请,就必须拒绝掉与这个申请相冲突的预约。 一般来说,如果PP大厦方面事先已经接受了一个会场预约,例如从10日到15日,就不会在接受与之相冲突的预约,例如从12日到17日。不过,有时出于经济利益,PP大厦方面有时会为了接受一个新的会场预约,而拒绝掉一个甚至几个之前预订的预约。 于是,礼堂管理员QQ的笔记本上笔记本上经常记录着这样的信息: 本题中为方便起见,所有的日期都用一个整数表示。例如,如果一个为期10天的会议从“90日”开始到“99日”,那么下一个会议最早只能在“100日”开始。 最近,这个业务的工作量与日俱增,礼堂的管理员QQ希望参加SHTSC的你替他设计一套计算机系统,方便他的工作。这个系统应当能执行下面两个操作: A操作:有一个新的预约是从“start日”到“end日”,并且拒绝掉所有与它相冲突的预约。执行这个操作的时候,你的系统应当返回为了这个新预约而拒绝掉的预约个数,以方便QQ与自己的记录相校对。 B操作:请你的系统返回当前的仍然有效的预约的总数。

输入输出格式

输入格式:

输入文件的第一行是一个整数n,表示你的系统将接受的操作总数。 接下去n行每行表示一个操作。每一行的格式为下面两者之一: “A start end”表示一个A操作; “B”表示一个B操作。

输出格式:

输出文件有n行,每行一次对应一个输入。表示你的系统对于该操作的返回值。

输入输出样例

输入样例#1:

6
A 10 15
A 17 19
A 12 17
A 90 99
A 11 12
B
输出样例#1:

0
0
2
0
1
2

说明

N< = 200000

1< = Start End < = 100000

Solution:

  一道思路特巧妙的题目。

  开始的思路是直接线段树染色,但是要维护的东西比较多,码量大,复杂不想调。

  于是观摩巨佬们的思路,发现本题树状数组+二分的思路实在是巧妙。

  因为每次加入一个区间,就会将与之冲突的区间删去,那么显然同一个$st$或者$ed$只能出现一次。

  我们选择记录当前$st$所对应的$ed$,再用树状数组单点维护每个区间的$st$出现的次数,然后每次需要加入一个区间$[x,y]$,就查找出$(0,y]$中有多少个区间,并二分出离当前区间最近的一个区间的起点,判断一下该区间是否与需要加入的区间有交集,有的话就计数、删掉该区间并继续二分,若无交集,因为区间是一个一个加入的,那么往前的区间一定之前就调整好了,所以再往前不会出现交集,不需要再二分了直接跳出循环。然后将需要加入的区间起点加入树状数组,并记录一下该起点所对应的终点,模拟一下就好了。

  时间复杂度显然$O(n\log^2 n)$(实际肯定是要快的多的,只是单纯从算法嵌套角度分析的最坏情况)。

代码:

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)>(b)?(b):(a))
using namespace std;
const int N=;
int n,sum[N],ed[N],ans,dlt; il int gi(){
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
return f?-a:a;
} il void update(int k,int c){while(k<N)sum[k]+=c,k+=k&-k;} il int query(int k){int ans=;while(k)ans+=sum[k],k-=k&-k;return ans;} int main(){
n=gi();
char s[];
int x,y;
while(n--){
scanf("%s",s);
if(s[]=='A'){
x=gi(),y=gi();
dlt=;int op;
while(op=query(y)){
int l=,r=y,m;
while(l<r){
m=l+r>>;
if(query(m)+<=op)l=m+;
else r=m;
}
if(ed[l]>=x)update(l,-),dlt++,ans--;
else break;
}
update(x,),ed[x]=y,ans++;
printf("%d\n",dlt);
}
else printf("%d\n",ans);
}
return ;
}

最新文章

  1. Web前端面试之HTML
  2. Android Hack1 使用weight属性实现视图的居中显示
  3. 关于 update别名 与update select
  4. 关于Web开发里并发、同步、异步以及事件驱动编程的相关技术
  5. ssh全屏退出的办法
  6. WCF-复合类型使用;传输图片
  7. JMeter处理jdbc请求后的响应结果
  8. HDUoj-------(1128)Self Numbers
  9. 使用BTRACE定位系统中慢的问题
  10. 简单的ROT13码编码与解码
  11. 偶尔转帖:AI会议的总结(by南大周志华)
  12. Delphi 6 Web Services初步评估之二(转)
  13. SQL Server 分组后取Top N
  14. Javascript进阶篇——浏览器对象—Location、Navigator、userAgent、screen对象
  15. Java多线程--让主线程等待所有子线程执行完毕
  16. qt学习笔记
  17. WPF 异步刷新页面,创建定时器
  18. Python数据类型之list和tuple
  19. 【BZOJ-2329&amp;2209】括号修复&amp;括号序列 Splay
  20. 散列表(HashTable)

热门文章

  1. Linux入门-第五周
  2. PHP导出数据到表格的实例
  3. nginx: [error] open() &quot;/var/run/nginx.pid&quot; failed (2: No such file or directory)
  4. Docker(二):Hello World
  5. SVN配置自启动-1053错误
  6. python3 练习题100例 (二十一)打印一定范围内的水仙花数
  7. stm32+lwip(四):网页服务器测试
  8. R语言绘图:时间序列分析
  9. python2.7练习小例子(二十五)
  10. python中的os,shutil模块的定义以及用法