题目描述

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行,每行一次对应一个输入。表示你的系统对于该操作的返回值。

二分+树状数组/线段树

还是用树状数组吧。

我们考虑所有接受的预约的开始时间都是严格递增的,那么我们建立Fenwick Tree,add(i,1)表示开始时间为i的预约存在,加入fwt

然后考虑拒绝的情况

二分查找所有开始时间小于等于当前预约结束时间的预约(只有这样才有可能被拒绝)

然后找到:开始时间与当前预约的结束时间最接近的一个预约。检查它的结束时间是否大于等于当前预约的开始时间建议画区间图

考虑未加入当前预约之前所有预约的开始、结束时间都是满足严格递增关系的,如果找到的最接近结束时间的都不与当前预约冲突,那在它之前的所有预约其结束时间严格递减,更不可能被拒绝。

所以直接break

而考虑右边(时间轴),如果能找到开始时间在当前预约的结束时间左边的预约,那就不可能跑到当前预约的右面。整体在当前预约右面的也一定不会被二分找到。

所以这样考虑到了所有情况

然后就统计一下输出就行了。

注意拒绝的时候还要add(position,-1),还有就是一开始就要查一下在当前预约的结束时间左边一共有多少预约。用这个二分。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<utility>
#include<iterator>
using namespace std;

int fwt[150010]={0},indexx[150010]={0};
int opnum,upat=0,stx,edx;
char ch=0;

inline int getsum(int pos)
{
	int sum=0;
	while (pos)
	{
		sum+=fwt[pos];
		pos-=(pos&(-pos));
	}
	return sum;
}

inline void add(int pos,int val)
{
	while (pos<=100010)
	{
		fwt[pos]+=val;
		pos+=(pos&(-pos));
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin>>opnum;
	for (int o=1;o<=opnum;o++)
	{
		cin>>ch;
		if (ch=='A') 
		{
			cin>>stx>>edx;
			int sum=0;
			while (1)
			{
				int l=1,r=edx,mid,apnum=getsum(edx),posx;
				if (!apnum) break;
				while (l<=r)
				{
					mid=(l+r)>>1;
					if (getsum(mid)==apnum)
					{
						posx=mid;
						r=mid-1;
					}
					else l=mid+1;
				}
				if (indexx[posx]>=stx)
				{
					sum++;
					add(posx,-1);
				}
				else break;
			}
			printf("%d\n",sum);
			add(stx,1); indexx[stx]=edx;
		}
		else printf("%d\n",getsum(100010));
	}
	return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.