【CF-1452E】Two Editorials (贪心)

题目链接: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\n", res);
}
posted @ 2020-11-30 16:26  tudouuuuu  阅读(97)  评论(0编辑  收藏  举报