约会安排 HDU - 4553

 寒假来了,又到了小明和女神们约会的季节。
  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会。与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事。
  我们已知小明一共有T的空闲时间,期间会有很多女神或者基友来找小明。
  作为一个操作系统曾经怒考71分的大神,小明想到了一个算法,即“首次适应算法”,根据操作系统课本的描述,就是找一段最靠前的符合要求的连续空间分配给每个请求,由此小明做出了一个决定:
  当一个基友来找小明时,小明就根据“首次适应算法”来找一段空闲的时间来和基友约好,如果找到,就说“X,let’s fly”(此处,X为开始时间),否则就说“fly with yourself”;
  当女神来找小明时,先使用一次“首次适应算法”,如果没有找到,小明就冒着木叽叽的风险无视所有屌丝基友的约定,再次使用“无视基友首次适应算法”,两次只要有一次找到,就说“X,don’t put my gezi”(此处,X为开始时间),否则就说“wait for me”
  当然,我们知道小明不是一个节操负无穷的人,如果和女神约会完,还有剩余时间,他还是会和原来约好的基友去dota的。(举个例子:小西(屌丝)和小明约好在1~5这个时间单位段内打dota,这时候,女神来和小明预约长度为3的时间段,那么最终就是1~3小明去和女神约会,搞定后在4~5和小西打dota)
  小明偶尔也会想要学习新知识,此时小明就会把某一个时间区间的所有已经预定的时间全部清空用来学习并且怒吼“I am the hope of chinese chengxuyuan!!”,不过小明一般都是三分钟热度,再有人来预定的话,小明就会按耐不住寂寞把学习新知识的时间分配出去。

Input

输入第一行为CASE,表示有CASE组测试数据;
每组数据以两个整数T,N开始,T代表总共的时间,N表示预约请求的个数;
接着的N行,每行表示一个女神或者基友的预约,“NS QT”代表一个女神来找小明约一段长为QT的时间,“DS QT”则代表一个屌丝的长为QT的请求,当然也有可能是小明想学知识了,“STUDY!! L R”代表清空L~R区间内的所有请求。

1. 1 <= CASE <= 30
2. 1 <= T, N <= 100000
3. 1 <= QT <= 110000
4. 1 <= L <= R <=T

Output

对于每一个case,第一行先输出“Case C:”代表是第几个case,然后N行,每行对应一个请求的结果(参照描述)。
输出样本(可复制此处):
“X,let's fly”,”fly with yourself”,”X,don't put my gezi”,”wait for me”,”I am the hope of chinese chengxuyuan!!”

Sample Input

1
5 6
DS 3
NS 2
NS 4
STUDY!! 1 5
DS 4
NS 2

Sample Output

Case 1:
1,let's fly
4,don't put my gezi
wait for me
I am the hope of chinese chengxuyuan!!
1,let's fly
1,don't put my gezi

解题思路:

把小明的基友和女神分开建树,如果是基友找小明更新基友树,女神找小明更新女神树和基友树(相信你能明白吧,女神可以无视基友,反之则不行。。)。还有一个要点就是连续区间的查询,需要用到从区间左端点开始(包括端点本身)最长连续区间长度(dl、vl数组),以及从区间右端开始最长连续区间长度(dr、vr数组),还有区间最长连续子区间的长度(dm、vm数组)

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 100020;
int cas, t, n;
int dl[maxn << 2], dr[maxn << 2], dm[maxn << 2];
int vl[maxn << 2], vr[maxn << 2], vm[maxn << 2];


void Build(int l, int r,int rt)
{
	dl[rt] = dr[rt] = dm[rt] = r - l + 1;
	vl[rt] = vr[rt] = vm[rt] = r - l + 1;
	if(l == r) return ;
	int m = (l + r) / 2;
	Build(l, m, rt << 1);
	Build(m + 1, r, rt << 1 | 1);
}

void push_down(int l, int r, int rt)
{
	int m = (l + r) / 2;
	dl[rt] = dl[rt << 1];
	dr[rt] = dr[rt << 1 | 1];

	vl[rt] = vl[rt << 1];
	vr[rt] = vr[rt << 1 | 1];

	dm[rt] = max(max(dm[rt << 1], dm[rt << 1 | 1]), dr[rt << 1] + dl[rt << 1 | 1]);
	vm[rt] = max(max(vm[rt << 1], vm[rt << 1 | 1]), vr[rt << 1] + vl[rt << 1 | 1]);

	if(dl[rt << 1] == m - l + 1)	dl[rt] += dl[rt << 1 | 1];
	if(dr[rt << 1 | 1] == r - m)	dr[rt] += dr[rt << 1];
	if(vl[rt << 1] == m - l + 1)	vl[rt] += vl[rt << 1 | 1];
	if(vr[rt << 1 | 1] == r - m)	vr[rt] += vr[rt << 1];
}

void push_up(int l, int r, int rt)
{
	int m = (l + r) / 2;
	if(dm[rt] == r - l + 1)
	{
		dl[rt << 1] = dr[rt << 1] = dm[rt << 1] = m - l + 1;
		dl[rt << 1 | 1] = dr[rt << 1 | 1] = dm[rt << 1 | 1] = r - m;
	}
	if(dm[rt] == 0)
	{
		dl[rt << 1] = dr[rt << 1] = dm[rt << 1] = 0;
		dl[rt << 1 | 1] = dr[rt << 1 | 1] = dm[rt << 1 | 1] = 0;
	}
	if(vm[rt] == r - l + 1)
	{
		vl[rt << 1] = vr[rt << 1] = vm[rt << 1] = m - l + 1;
		vl[rt << 1 | 1] = vr[rt << 1 | 1] = vm[rt << 1 | 1] = r - m;
	}
	if(vm[rt] == 0)
	{
		vl[rt << 1] = vr[rt << 1] = vm[rt << 1] = 0;
		vl[rt << 1 | 1] = vr[rt << 1 | 1] = vm[rt << 1 | 1] = 0;
	}
}

void update(int L, int R, int val, int l, int r, int rt, bool flag)
{
	if(l >= L && r <= R)
	{
		if(flag)
		{
			dl[rt] = dr[rt] = dm[rt] = val * (r - l + 1);
			vl[rt] = vr[rt] = vm[rt] = val * (r - l + 1);	
		}
		else 
			dl[rt] = dr[rt] = dm[rt] = val * (r - l + 1);
		return ;
	}
	push_up(l, r, rt);
	int m = (l + r) / 2;
	if(m >= L)
		update(L, R, val, l, m, rt << 1, flag);
	if(m < R)
		update(L, R, val, m + 1, r, rt << 1 | 1, flag);
	push_down(l, r, rt);
}

int query(int x, int l, int r, int rt, bool flag)   ///基友查询
{
	if(l == r)  return l;
	int m = (l + r) / 2;
	push_up(l, r, rt);
	if(flag)
	{
		if(vm[rt << 1] >= x)							
			return query(x, l, m, rt << 1, flag);
		else if(vr[rt << 1] + vl[rt << 1 | 1] >= x) 	
			return m - vr[rt << 1] + 1;
		else 											
			return query(x, m + 1, r, rt << 1 | 1, flag);
	}
	else 
	{	
		if(dm[rt << 1] >= x)							
			return query(x, l, m, rt << 1, flag);
		else if(dr[rt << 1] + dl[rt << 1 | 1] >= x) 	
			return m - dr[rt << 1] + 1;
		else 											
			return query(x, m + 1, r, rt << 1 | 1, flag);
	}
}


int main()
{
	cin >> cas;
	int snk = 1;
	while(cas--)
	{
		scanf("%d%d", &t, &n);
		printf("Case %d:\n", snk++);
		Build(1, t, 1);
		char op[20];
		for(int i = 1; i <= n; ++ i)
		{
			scanf("%s", op);
			if(op[0] == 'N')   ///女神约会
			{
				int x;
				scanf("%d", &x);
				int tmp;
					if(dm[1] >= x)
					{
						tmp = query(x, 1, t, 1, false);
						printf("%d,don't put my gezi\n", tmp);
						update(tmp, tmp + x - 1, 0, 1, t, 1, true);
					}
					else if(vm[1] >= x)
					{
						tmp = query(x, 1, t, 1, true);
						printf("%d,don't put my gezi\n", tmp);
						update(tmp, tmp + x - 1, 0, 1, t, 1, true);
					}
					else 
					{
						printf("wait for me\n");
					}
				
			}
			else if(op[0] == 'D')  ///基友dota
			{
				int x;
				scanf("%d", &x);
				int tmp = dm[1];
				if(tmp < x)
					cout << "fly with yourself" << endl;
				else 
				{
					tmp = query(x, 1, t, 1, false);
		        	printf("%d,let's fly\n", tmp);
					update(tmp, tmp + x - 1, 0, 1, t, 1, false); 
				}
			}
			else 
		    {
				int ll, rr;
				scanf("%d%d", &ll, &rr);
				printf("I am the hope of chinese chengxuyuan!!\n");
				update(ll, rr, 1, 1, t, 1, true);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/aqa2037299560/article/details/82872720