P2107 小 Z 的 AK 计划 贪心

P2107 小 Z 的 AK 计划

题目大意

机房一条街有 \(n\) 个机房,第 \(i\) 个机房的坐标为 \(x_i\),小 Z 的家坐标为 \(0\)。小 Z 在街上移动的速度为 \(1\),即从 \(x_1\)\(x_2\) 所耗费的时间为 \(|x_1 - x_2|\)

小 Z 到达第 \(i\) 个机房后,可以花 \(t_i\) 的时间想题,然后瞬间 AK;当然,也可以过机房而不入。

小 Z 现在只有 \(m\) 个单位时间。现在他想知道自己最多能在多少个机房 AK,希望你帮帮他。

说明/提示

对于 \(30\%\) 的数据,\(n \leq 20\)

对于 \(60\%\) 的数据,\(n \leq 1000\)

对于 \(100\%\) 的数据,\(1 \leq n \leq 10^5\)\(0 \leq m,x_i \leq 10^{18}\)\(0 \leq t_i \leq 10^9\)

思路

\(n \le 1000\) 时,我们显然是可以通过动态规划做的。但是这题最大的 \(n\) 达到了\(10^5\),DP 时间复杂度为 \(O(nm)\),超飞了。于是我们想可不可以贪心求解。

我们先一直往前走,走到下一个机房,看在还剩下的时间内能不能AK,若是可以AK,就放进priority_queue里面;若不可以AK,那么试试将前面选择AK的耗时最大的一或多个去掉,再看看是否AK,重复这么做,每次统计可以AK的机房的最大值,就没了。

那么正确性怎么证明呢?我只能说显然

/*
    @ Author:       Eric / Sky__White
    @ Filename:     P2107.cpp
    @ Date:         10/07/2026
    @ Email:        acwing@foxmail.com / 17802535158@163.com
*/

#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <queue>

namespace std {
    class Read {
        public:
        template<typename T>
        inline Read operator >> (T & x) {
            T sum = 0, opt = 1;
            char ch = getchar();
            while(!isdigit(ch)) opt = (ch == '-') ? -1 : 1, ch = getchar();
            while( isdigit(ch)) sum = (sum << 1) + (sum << 3) + (ch ^ 48), ch = getchar();
            x = sum * opt;
            return *this;
        }
    };
}
#define int long long
#define all(a) a.begin(), a.end()

using namespace std; Read fin;

signed main() {
    int n, m; cin >> n >> m;

    vector<pair<int, int> > arr(n + 1);

    for (int i = 1; i <= n; i ++ ) {
        fin >> arr[i].first >> arr[i].second;
    }

    sort(1 + all(arr));

    int dis = 0, sum = 0, res = 0, ans = 0;
    priority_queue<int> q;

    for (int i = 1; i <= n; i ++ ) {
        dis = arr[i].first; sum += arr[i].second; ans ++ ;
        q.push(arr[i].second);

        while (q.size() and sum + dis > m) {
            sum -= q.top(); q.pop();
            ans -- ;
        }

        cout << ans << endl;
        
        res = max(res, ans); 
    }

    cout << res << endl;
}
posted @ 2026-07-16 08:40  Skyかざまこうと  阅读(4)  评论(0)    收藏  举报