Painting the Fence
You have a long fence which consists of n n n sections. Unfortunately, it is not painted, so you decided to hire q q q painters to paint it. i i i-th painter will paint all sections x x x such that l i ≤ x ≤ r i l_i \le x \le r_i li≤x≤ri.
Unfortunately, you are on a tight budget, so you may hire only q − 2 q - 2 q−2 painters. Obviously, only painters you hire will do their work.
You want to maximize the number of painted sections if you choose q − 2 q - 2 q−2 painters optimally. A section is considered painted if at least one painter paints it.
Input
The first line contains two integers n n n and q q q ( 3 ≤ n , q ≤ 5000 3 \le n, q \le 5000 3≤n,q≤5000) — the number of sections and the number of painters availible for hire, respectively.
Then q q q lines follow, each describing one of the painters: i i i-th line contains two integers l i l_i li and r i r_i ri ( 1 ≤ l i ≤ r i ≤ n 1 \le l_i \le r_i \le n 1≤li≤ri≤n).
Output
Print one integer — maximum number of painted sections if you hire q − 2 q - 2 q−2 painters.
Example
i n p u t \tt input input |
---|
7 5 1 4 4 5 5 6 6 7 3 5 |
o u t p u t \tt output output |
7 |
i n p u t \tt input input |
---|
4 3 1 1 2 2 3 4 |
o u t p u t \tt output output |
2 |
i n p u t \tt input input |
---|
4 4 1 1 2 2 2 3 3 4 |
o u t p u t \tt output output |
3 |
Tutorial
由题意得, n n n 和 q q q 的范围为 3 ≤ n , q ≤ 5000 3 \le n, q \le 5000 3≤n,q≤5000,所以可以用 O ( n 2 ) \mathcal O(n ^ 2) O(n2) 的复杂度解决这个问题
我们可以用一层循环遍历其中一个画家,然后将其画的范围去掉,此时如果去掉第二个画家,只有那些现在被画一次的位置才可能被抹去,此时可以用前缀和计算区间内有多少个这个位置,然后枚举每一个画家,看解雇这个画家后能少画多少位置
此解法时间复杂度为 O ( max ( n , q ) 2 ) \mathcal O(\max(n, q) ^ 2) O(max(n,q)2)
Solution
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, q, ans = 0;
cin >> n >> q;
vector<int> left(q), right(q), cnt(n + 1), pre(n + 2);
for (int i = 0; i < q; ++i) {
cin >> left[i] >> right[i];
// --left[i], --right[i];
for (int j = left[i]; j <= right[i]; ++j) {
cnt[j]++;
}
}
for (int i = 0; i < q; ++i) {
int l = left[i], r = right[i], count = 0;
for (int j = l; j <= r; ++j) {
cnt[j]--;
}
for (int j = 0; j <= n; ++j) {
pre[j + 1] = pre[j];
if (cnt[j] >= 1) {
count++;
}
pre[j + 1] += cnt[j] == 1;
}
for (int j = 0; j < i; ++j) {
ans = max(ans, count - (pre[right[j] + 1] - pre[left[j]]));
}
for (int j = l; j <= r; ++j) {
cnt[j]++;
}
}
cout << ans << endl;
return 0;
}