#include #include #include #include #include #include /** * Meeting Free Fridays * * First sort the meetings by end time. Then let free(i, j) be the maximum * amount of free time you can have by taking i of the first j meetings. * free(i, j) = max free(l, j - 1) + start(i) - end(l) over all l < i where l's * meeting ends before i's meeting begins. Computing this naively is O(n^3) * since there are O(n^2) states and O(n) transitions. To speed this up, we can * optimize the transitions to O(1) by storing the maximum values of * free(l, j - 1) - end(l) for all j and updating appropriately. */ using Interval = std::array; using Event = std::array; static constexpr int64_t INF = 1e12; int main() { int32_t n; int64_t t, k; std::cin >> n >> t >> k; std::vector meetings(n); for (auto& [s, e] : meetings) { std::cin >> s >> e; } std::ranges::sort(meetings, [](const auto& l, const auto& r){ return l[1] < r[1]; }); std::vector events; events.reserve(2 * n); for (int32_t i = 0; i < n; ++i){ auto [s, e] = meetings[i]; events.push_back({s, +1, i}); events.push_back({e, -1, i}); } std::ranges::sort(events); // dp is the maximum value of free(i, j) - end(i) std::vector dp(n + 1, -INF); // byMeeting is free(i, j) above. std::vector> byMeeting(n); int32_t ans = 0; for (auto [time, op, idx] : events) { auto [s, e] = meetings[idx]; auto& row = byMeeting[idx]; if (op == 1) { row.assign(idx + 2, -INF); row[1] = s; for (int32_t j = 1; j + 1 < row.size(); ++j) { row[j + 1] = std::max(row[j + 1], dp[j] + s); } } else { int64_t after = t - e; for (int32_t j = 1; j < row.size(); ++j) { if (after + row[j] >= k) { ans = std::max(ans, j); } dp[j] = std::max(dp[j], row[j] - e); } } } std::cout << ans << '\n'; return 0; }