[SHOI2009]Booking

[SHOI2009]Booking
題目描述
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:
6A 10 15A 17 19A 12 17A 90 99A 11 12B

輸出樣例#1:
002012

說明
N< = 200000
1< = Start End < = 100000

題解:
類似染色問題,維護個數,最左的種類,最右的種類,合併時想一下就可以想出來了。
對於修改後延伸出區間的處理,只需要記錄下來每種的區間,然後修改就行(原來我想二分的,被舒老師無情碾壓)

代碼:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

const int max_n = 200001;
const int inf = 1e6+7;

struct node
{
	int l,r;
	int num,left,right,delta;
}tree[max_n<<2];

int b[max_n][2];
char c;
int n,x,y,num;

inline node update(node a,node b)
{
	node ans;
	ans.num=a.num+b.num;
	ans.left=a.left;
	ans.right=b.right;
	ans.l=a.l;
	ans.r=b.r;
	if(a.right==b.left && a.right!=0) ans.num--;
	ans.delta=-1;
	return ans;
}

inline void pushdown(int now)
{
	if(tree[now].delta!=-1)
	{
		tree[now<<1].num= tree[now].delta==0 ? 0 : 1;
		tree[now<<1].left=tree[now].delta;
		tree[now<<1].right=tree[now].delta;
		tree[now<<1].delta=tree[now].delta;
		tree[now<<1|1].num= tree[now].delta==0 ? 0 : 1;
		tree[now<<1|1].left=tree[now].delta;
		tree[now<<1|1].right=tree[now].delta;
		tree[now<<1|1].delta=tree[now].delta;
		tree[now].delta=-1; 
	}
}

void build(int now,int l,int r)
{
	tree[now].l=l; tree[now].r=r; tree[now].delta=-1;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(now<<1,l,mid);
	build(now<<1|1,mid+1,r);
}

void change(int now,int l,int r,int val)
{
	int lr=tree[now].l,rr=tree[now].r;
	if(l<=lr && rr<=r)
	{
		tree[now].num= val==0 ? 0 : 1;
		tree[now].delta=val;
		tree[now].left=tree[now].right=val;
		return;
	}
	pushdown(now);
	int mid=(lr+rr)>>1;
	if(l<=mid) change(now<<1,l,r,val);
	if(r>mid) change(now<<1|1,l,r,val);
	tree[now]=update(tree[now<<1],tree[now<<1|1]);
}

node query(int now,int l,int r)
{
	int lr=tree[now].l,rr=tree[now].r;
	if(l<=lr && rr<=r) return tree[now];
	pushdown(now);
	int mid=(lr+rr)>>1;
	if(l<=mid && !(r>mid)) return query(now<<1,l,r);
	else if(r>mid && !(l<=mid)) return query(now<<1|1,l,r);
	else return update(query(now<<1,l,r),query(now<<1|1,l,r));
}

inline void work1()
{
	scanf("%d%d",&x,&y);
	b[++num][0]=x; b[num][1]=y;
	node tmp=query(1,x,y);
	printf("%d\n",tmp.num);
	change(1,min(x,b[tmp.left][0]),max(y,b[tmp.right][1]),0);
	change(1,x,y,num);
}

inline void work2()
{
	printf("%d\n",tree[1].num);
}

int main()
{
	scanf("%d",&n);
	b[0][0]=inf; b[0][1]=0;
	build(1,1,max_n-1);
	for(int i=1; i<=n; ++i)
	{
		cin>>c;
		if(c=='A') work1();
		else work2();
	}
	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章