题目描述:
农夫约翰为他的牛开设了一个游泳池,他认为这将帮助它们放松并产出更多的奶。
为了确保安全,他雇佣了 $ N $ 头奶牛作为救生员,每头奶牛的工作班次都是一段连续的时间。
为了简单起见,游泳池每天的开放时间从时刻 $ 0 $ 到时刻 $ 1000 $ 。
每个奶牛的工作班次都可以用两个整数来描述,它们分别表示该奶牛工作班次的开始时刻和结束时刻。
例如,从时刻 $ t = 4 $ 开始工作并在时刻 $ t=7 $ 结束工作的救生员,它的工作时间为三个时间单位(请注意,时间“段”两端的端点是时间轴上的“点”)。
不幸的是,由于资金紧张问题,约翰不得不解雇一头奶牛。
请问通过合理裁员,剩余救生员的工作班次仍然可以覆盖的最大时间有多长?
一个时间间隔内如果存在至少一名救生员当值,那么这个时间间隔就认为是被覆盖的。
输入格式
第一行包含整数 $ N $ 。
接下来 $ N $ 行,每行描述一个救生员的工作班次,包含两个整数,表示一个救生员的开始工作时刻和结束工作时刻。
所有时刻各不相同,不同救生员的工作班次可能有覆盖。
输出格式
输出一个整数,表示解雇掉一头奶牛后,剩余救生员的工作班次仍然可以覆盖的最长时间。
数据范围
$ 1 \le N \le 100 $
输入样例:
输出样例:
题解:
由于数据范围比较小,所以方法比较多。
- 直接使用区间加,每次枚举删除的区间,求出删除之后得到的区间。
- 使用区间合并。区间合并,维护一个区间,遇到一个新区间时进行比较,如果新区间的起点小于所维护区间的终点,更新维护区间的终点为二者终点的最大值(包含了两个区间相交,和相容)。 如果新区间的起点大于所维护区间的终点,那么更新所维护区间的起点和终点为新区间(相离)。
- 使用区间加,把每一段都加上,那么最后得到的数组中。如果元素等于 $ 1 $ ,说明只被一个区间覆盖,使用一个新的前缀和数组统计 $ 1 $ 的个数。这样的话可以很方便的计算出每一个区间中唯一覆盖的长度。这样的话就可以得到删除一个区间后,剩余了多少长度。
代码:
方法二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| using namespace std; using namespace FAST_IO; const ll mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const ll INF_LL = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-5; const int maxn = 1e3 + 10; const int maxm = 1e5 + 10; int t, n, m, k; vector<PII> a; int main() {
#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif ios::sync_with_stdio(false); cin.tie(0); cin >> n; for (int i = 1, x, y; i <= n; i++) { cin >> x >> y; a.push_back({x, y}); } sort(a.begin(), a.end()); int ans = 0; for (int i = 0; i < a.size(); i++) { int sum = 0, st = -1, ed = -1; for (int j = 0; j < a.size(); j++) { if (j != i) { if (ed >= a[j].first) { ed = max(ed, a[j].second); } else { sum += ed - st; st = a[j].first; ed = a[j].second; } } } sum += ed - st; ans = max(ans, sum); } cout << ans << endl; return 0; }
|
方法三
注意这里是区间长度,化为点的话就是前闭后开,这样的话区间加就不需要 a[r + 1]--
而是变成了 a[r]--
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| using namespace std; using namespace FAST_IO; const ll mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const ll INF_LL = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-5; const int maxn = 1e3 + 10; const int maxm = 1e5 + 10; int t, n, m, k; int a[maxn]; int b[maxn]; vector<PII> c; int main() {
#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif ios::sync_with_stdio(false); cin.tie(0); cin >> n; for (int i = 1, x, y; i <= n; i++) { cin >> x >> y; c.push_back({x, y}); a[x]++; a[y]--; } int sum = 0; if (a[0]) sum = 1; if (a[0] == 1) b[0] = 1; for (int i = 1; i <= 1001; i++) { a[i] += a[i - 1]; if (a[i]) sum++; if (a[i] == 1) b[i] = 1; b[i] += b[i - 1]; } int ans = INF; for (int i = 0; i < c.size(); i++) { if (c[i].first == 0) { ans = min(ans, b[c[i].second - 1]); } else { ans = min(ans, b[c[i].second-1] - b[c[i].first - 1]); } } cout << sum - ans << endl; return 0; }
|