大致题意
有$m$个长度不等的听题人区间。 让你设计两个长度为$k$的讲题人区间,使得$m$个听题人区间在选择其中的一个讲题人区间进行重叠后,其重叠的总和最大。
题目描述
Berland regional ICPC contest has just ended. There were m participants numbered from $1$ to $m$, who competed on a problemset of $n$ problems numbered from $1$ to $n$.
Now the editorial is about to take place. There are two problem authors, each of them is going to tell the tutorial to exactly $k$ consecutive tasks of the problemset. The authors choose the segment of $k$ consecutive tasks for themselves independently of each other. The segments can coincide, intersect or not intersect at all.
The $i^{th}$ participant is interested in listening to the tutorial of all consecutive tasks from $l_i$ to $r_i$. Each participant always chooses to listen to only the problem author that tells the tutorials to the maximum number of tasks he is interested in. Let this maximum number be $a_i$. No participant can listen to both of the authors, even if their segments don’t intersect.
The authors want to choose the segments of $k$ consecutive tasks for themselves in such a way that the sum of ai over all participants is maximized.
Input
The first line contains three integers $n$,$m$ and $k$ ($1≤n,m≤2000$, $1≤k≤n$) — the number of problems, the number of participants and the length of the segment of tasks each of the problem authors plans to tell the tutorial to.
The $i^{th}$ of the next $m$ lines contains two integers $l_i$ and $r_i$ $(1≤l_i≤r_i≤n)$ — the segment of tasks the $i^{th}$ participant is interested in listening to the tutorial to
Output
Print a single integer — the maximum sum of ai over all participants.
样例
示例1
Input
10 5 3
1 3
2 4
6 9
6 9
1 8
Output
14
示例2
Input
10 3 3
2 4
4 6
3 5
Output
8
示例3
Input
4 4 1
3 3
1 1
2 2
4 4
Output
2
示例4
Input
5 4 5
1 2
2 3
3 4
4 5
Output
8
Note
In the first example the first author can tell the tutorial to problems from $1$ to $3$ and the second one — from $6$ to $8$. That way the sequence of ai will be $[3,2,3,3,3]$. Notice that the last participant can’t listen to both author, he only chooses the one that tells the maximum number of problems he’s interested in.
In the second example the first one can tell problems $2$ to $4$, the second one — $4$ to $6$.
In the third example the first one can tell problems $1$ to $1$, the second one — $2$ to $2$. Or $4$ to $4$ and $3$ to $3$. Every pair of different problems will get the same sum of $2$.
In the fourth example the first one can tell problems $1$ to $5$, the second one — $1$ to $5$ as well.
算法1
(贪心, 前缀和) $O(mlog(m) + mn)$
- 假设两个讲题人的区间中点分别是$M1$,和$M2$, 那么对于任意一个听题人区间而言, 它一定会选择$M1$和$M2$中与听题人中点更接近的区间来完成更多的题目覆盖.
- 因此我们对
m
个听题人区间的中点进行排序,必然有前一部分听题人听第一个讲题人,后一部分听题人听第二个讲题人 - 从前往后枚举第一个讲题人的所有可能区间,并记录前面部分从第
1
个到第i
个讲题人的可能最大覆盖 - 从后往前枚举第二个讲题人的所有可能区间,并记录后面部分从第
m
个到第i
个讲题人的可能最大覆盖 - 记录最大覆盖时, 可以用一个辅助数组滚动记录当前枚举位置的覆盖前(后)缀和。
- 枚举分隔位置, 找到两个覆盖的最大和
时间复杂度
- 对听题人的中点排序需要 $mlog(m)$的时间
- 枚举两个讲题人分别各自需要 $O(mn)$的时间
- 计算答案需要$O(m)$的时间
- 故总时间复杂度为 $O(mlog(m) + mn)$
C++ 代码
typedef pair<int, int> PII;
const int MAXN = 2020;
int preSumMax[MAXN];
int sufSumMax[MAXN];
int preSumTemp[MAXN];
int sufSumTemp[MAXN];
PII students[MAXN];
int calc(int l1, int r1, int l2, int r2){
return max(0, min(r1, r2) - max(l1, l2) + 1);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n, m, k;
cin >> n >> m >> k;
for(int i = 1; i <= m; i++){
int l, r;
cin >> l >> r;
students[i] = {l, r};
}
sort(students + 1, students + m + 1, [&](PII& s1, PII& s2){
return s1.first + s1.second < s2.first + s2.second;
});
// first teacher
for(int l = 1; l + k - 1 <= n; l++){
for (int i = 1; i <= m; i++){
PII& s = students[i];
preSumTemp[i] = preSumTemp[i - 1] + calc(s.first, s.second, l, l + k - 1);
preSumMax[i] = max(preSumTemp[i], preSumMax[i]);
}
}
// second teacher
for(int r = n; r - k + 1>= 1; r--){
for (int i = m; i >= 1; i--){
PII& s = students[i];
sufSumTemp[i] = sufSumTemp[i + 1] + calc(s.first, s.second, r - k + 1, r);
sufSumMax[i] = max(sufSumMax[i], sufSumTemp[i]);
}
}
int ans = 0;
for(int i = 1; i <= m; i++){
ans = max(preSumMax[i - 1] + sufSumMax[i], ans);
}
printf("%d\n", ans);
return 0;
}