LOJ#6085. 「美团 CodeM 资格赛」优惠券

版权声明:转载请注明 https://blog.csdn.net/qq_33831360/article/details/88563851

题目描述

一个有门禁的大楼,初始时里面没有人。

现在有一些人在进出大楼,每个人都有一个唯一的编号。现在有他们进出大楼的记录,但是有些被污染了,只能知道这里有一条记录,具体并不能知道。

一个人只有进大楼,才能出大楼,如果在大楼内,他必须先出去,才能再进来。

现在想知道这个记录是否错误,如果错误,请求出最早的错误在哪一行。

注释:人有无穷多个,记录中没有提到的人也可以进出大楼。

输入格式

第一行一个整数 m,表示共 m条记录。
接下来 m 行,每行一条记录。
记录是以下三种之一:

  • I x,表示x进入大楼。

  • O x,表示x走出大楼。

  • ?,表示不知道。

输出格式

如果没有错误,输出 -1。

否则输出第一行错误的位置。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这个题其实不难,但一时脑抽想错了(注意loj描述与原题稍有不同)

首先,如果有一处出错,就要用到前面一个“?”,具体哪一个呢~

比方说a进入,但他已经进了,那a上次进之前“?”无论怎么改都不能改变a进入的事实,不然上次a进入的记录就是错的

即在上次a进入之后找一个“?”让a出去,根据贪心思想,这个“?”要尽量靠前,越靠后的“?”可以用于解决下次问题记录的可能性越大。这个可以用set维护“?”的位置。

//auto   是c++11新特性

#include <iostream>
#include <cstdio>
#include <set>

using namespace std;

int In[110000],Out[110000];
set<int> s;

int main() {
	int m,sum = 0; cin >> m;
	for (int i = 1,x; i <= m; i++) {
		char opt; cin >> opt; 
		if (opt == '?') s.insert(i);
		else {
			cin >> x;
			if (opt == 'I') {
				if (In[x]) {
					auto it = s.upper_bound(In[x]);
					if (it == s.end()) {
						cout << i;
						return 0;
					}
					s.erase(it);
				}
				In[x] = i; Out[x] = 0;
			} else {
				if (!In[x]) {
				    auto it = s.upper_bound(Out[x]);
					if (it == s.end()) {
						cout << i;
						return 0;
					}
					s.erase(it);
			    }
				In[x] = 0; Out[x] = i;
			}
		}
				
	}
	puts("-1");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33831360/article/details/88563851
今日推荐