题目:http://codeforces.com/contest/1015/problem/A
题目大意:n个线段 [l, r], 然后1~m个点,输出哪些点不属于任何线段。
当然是个水题,时间复杂度O(n*m), 如果 n,m <= 10^7呢?
可以用前缀和O(n+m)解答:
给出 l,r 暴力想法直接 vis[l]~vis[r] 标记 1,但是有更好的想法。
将 vis[l]++, vis[r+1]-- ,求前缀和的时候,虽然中间的没有标记1,但是前缀和往后延申就达到标记效果了。将vis[r+1]--, 传到r+1的时候就(-1) + 1 = 0, 也就是没有出现过了。
例如 : 点1 2 3 4 5
给出线段 【2 4】, 【4,5】;可以看出答案为 1
点 0 1 2 3 4 5 6
[2,4] 0 0 1 0 0 -1 0
[4,5] 0 0 1 0 1 0 -1
前缀和 0 0 1 1 2 2 1(只有点1为0)
AC代码(原题解):
#include <bits/stdc++.h>
using namespace std;
int main() {
#ifdef _DEBUG
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int n, m;
cin >> n >> m;
vector<int> cnt(m + 2);
for (int i = 0; i < n; ++i) {
int l, r;
cin >> l >> r;
++cnt[l];
--cnt[r + 1];
}
for (int i = 1; i <= m; ++i)
cnt[i] += cnt[i - 1];
vector<int> ans;
for (int i = 1; i <= m; ++i) {
if (cnt[i] == 0)
ans.push_back(i);
}
cout << ans.size() << endl;
for (auto it : ans) cout << it << " ";
cout << endl;
return 0;
}