当前位置: 代码迷 >> 综合 >> CF - 420B - Online Meeting(思维)
  详细解决方案

CF - 420B - Online Meeting(思维)

热度:90   发布时间:2024-01-10 12:52:08.0

题意: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;
}


  相关解决方案