题目链接:https://codeforces.ml/contest/1452/problem/E
题目大意
给定 (m) 个人,他们感兴趣的区间在 ([1,n]) 的区间内,有两个老师进行授课,老师们的授课区间长度为 (k),每个人只能听一个老师授课,求所有人听到课的长度总和最大。
思路
对于一个老师和一个同学,当老师区间从左向右移动时,同学能听到的课的长度为0->最大->0,因此贪心地想能够在中点处达到最大。
对每个同学的中点位置进行排序,将中点位置小的排在前面,重点位置大的排在后面,从后往前扫,每次记录 ([j,m]) 位同学能够达到的和的最大值,用这个作为第二个老师授课的根据。
再枚举第一个老师的授课位置,枚举听第一个老师授课的同学数量,再加上之前记录的听第二个授课老师的 ([j,m]) 位同学能够达到的和的最大值,求最大值。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2005;
struct node {
int l, r;
} nd[MAXN];
int sum[MAXN];
int main() {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &nd[i].l, &nd[i].r);
}
sort(nd + 1, nd + 1 + m, [&](const node &ta, const node &tb) {
return ta.l + ta.r < tb.l + tb.r;
});
for (int i = 1; i <= n - k + 1; i++) {
int cur = 0;
for (int j = m; j >= 1; j--) {
cur += max(0, min(i + k, nd[j].r+1) - max(i, nd[j].l));
sum[j] = max(sum[j], cur);
}
}
int res = sum[0];
for (int i = 1; i <= n - k + 1; i++) {
int cur = 0;
for (int j = 1; j <= m; j++) {
cur += max(0, min(i + k, nd[j].r+1) - max(i, nd[j].l));
res = max(res, cur + sum[j + 1]);
}
}
printf("%d
", res);
}