题意:n 个人参加线上会议,某经理记录了中间一段时间的 m 条上下线记录(1?≤?n,?m?≤?105)。+ 表示上线,- 表示下线。leader是指只要有人在线,他都在线的人。求所有可能的leader。
题目链接:http://codeforces.com/problemset/problem/420/B
——>>这样的一种人,他们在记录中的第一条记录是下线的,定义为xx。。
三个断言:
1)如果xx存在,那么出现的人中,leader只可能是最后出现的那个xx。。
2)如果xx不存在,那么出现的人中,leader只可能是第一个登录的人。。
3)没出现过的人都可以是leader。。
#include <cstdio>
#include <set>using std::set;const int MAXN = 100000 + 10;int n, m;
char op[MAXN];
int p[MAXN];
int sum, leader;
int firstPlus = -1, lastInfinite = -1;
bool vis[MAXN];void Init()
{sum = n;for (int i = 1; i <= n; ++i){vis[i] = true;}
}void Read()
{for (int i = 1; i <= m; ++i){getchar();scanf("%c%d", op + i, p + i);if (op[i] == '-' && vis[p[i]] == true){lastInfinite = p[i];}if (firstPlus == -1 && op[i] == '+'){firstPlus = p[i];}if (vis[p[i]]){vis[p[i]] = false;--sum;}}
}void Solve()
{set<int> se;leader = lastInfinite == -1 ? firstPlus : lastInfinite;if (lastInfinite != -1){se.insert(leader);}for (int i = 1; i <= m; ++i){if (op[i] == '+'){se.insert(p[i]);if (se.find(leader) == se.end()){leader = -1;break;}}else{if (!se.empty()){se.erase(p[i]);}if (!se.empty() && se.find(leader) == se.end()){leader = -1;break;}}}if (leader != -1){vis[leader] = true;++sum;}
}void Output()
{printf("%d\n", sum);if (sum == 0) return;bool first = true;for (int i = 1; i <= n; ++i){if (vis[i]){if (first){first = !first;}else{printf(" ");}printf("%d", i);}}puts("");
}int main()
{while (scanf("%d%d", &n, &m) == 2){Init();Read();Solve();Output();}return 0;
}