题目描述
一个有门禁的大楼,初始时里面没有人。
现在有一些人在进出大楼,每个人都有一个唯一的编号。现在有他们进出大楼的记录,但是有些被污染了,只能知道这里有一条记录,具体并不能知道。
一个人只有进大楼,才能出大楼,如果在大楼内,他必须先出去,才能再进来。
现在想知道这个记录是否错误,如果错误,请求出最早的错误在哪一行。
注释:人有无穷多个,记录中没有提到的人也可以进出大楼。
输入格式
第一行一个整数 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;
}