1 条题解

  • 0
    @ 2026-4-22 15:01:10

    题意翻译

    nn 个赌场,编号 11nn。第 ii 个赌场有三个参数 li,ri,realil_i, r_i, real_i,满足 lirealiril_i \le real_i \le r_i。初始你有 kk 枚硬币。
    你可以在当前硬币数 xx 满足 lixril_i \le x \le r_i 时去赌场 ii 玩一次,之后硬币数变为 realireal_i
    每个赌场最多去一次,顺序任意。求最终能获得的最大硬币数。

    核心观察

    因为 realilireal_i \ge l_i,所以每次游戏后硬币数 不会减少(可能不变或增加)。
    这意味着随着你进行游戏,可玩的赌场集合只会扩大(因为 lil_i 是下限,curcur 增大后更多赌场的 lil_i 会被满足)。

    因此,贪心策略是:
    在当前可玩的赌场中,总是选择 realireal_i 最大的那个
    这可以立即提升 curcur,且不会破坏未来的可能性(因为更大的 curcur 只会让更多赌场变得可玩)。

    算法步骤

    1. 将所有赌场按 lil_i 升序排序。
    2. 维护一个指针 ptr 指向排序后的数组,以及一个最大堆(优先队列)存放当前已解锁的赌场的 realireal_i 值(以及对应的 rir_i)。
    3. 令当前硬币数 cur = k
    4. 循环:
      • ptr 指向的、满足 licurl_i \le cur 的所有赌场加入堆中(ptr 后移)。
      • 从堆中弹出元素(按 realireal_i 从大到小),但 只保留那些 ricurr_i \ge cur 的赌场(因为若 ri<curr_i < cur,赌场已不可玩,直接丢弃)。
      • 如果堆为空 → 无法继续,结束循环。
      • 否则,取出堆顶(最大 realireal_i),令 cur = real_i,继续循环。
    5. 输出最终的 cur

    复杂度分析

    • 排序 O(nlogn)O(n \log n)
    • 每个赌场最多入堆一次、出堆一次,堆操作 O(logn)O(\log n)
    • 总复杂度 O(nlogn)O(n \log n) 每个测试用例,总 nn 不超过 10510^5,可以通过。

    正确性证明

    引理:在任意时刻,若存在多个可玩的赌场,选择 realireal_i 最大的那个不会比选择任何其他赌场更差。

    证明:设当前硬币数为 curcur,有两个可玩赌场 AABB,且 realArealBreal_A \ge real_B

    • 若先玩 AA,则新硬币数为 realAreal_A。此时 BB 是否仍可玩?因为 realArealBlBreal_A \ge real_B \ge l_BcurrBcur \le r_BBB 原可玩),但 realAreal_A 可能大于 rBr_B 导致 BB 不可玩。然而,若 realA>rBreal_A > r_B,则 BBrB<realAr_B < real_A,而 realArealBreal_A \ge real_B,故 realBrB<realAreal_B \le r_B < real_A。这意味着即使先玩 BB,新硬币数 realBreal_B 仍小于 rBr_B,所以 BB 依然可玩(realBrBreal_B \le r_B),但 AA 可能因为 realBreal_B 不满足 lAl_A 而不可玩?注意 lAcurl_A \le curAA 原可玩),且 currealBcur \le real_B?不,realBreal_B 可能小于 curcur?但 realBlBreal_B \ge l_BlBl_B 可能小于 curcur?实际上 realBreal_B 可能小于 curcur(例如 realB=curreal_B = cur),但 currBcur \le r_B 成立,所以 BB 玩完后硬币数不变或增加。若 realB<realAreal_B < real_A,则先玩 BBAA 可能因 lA>realBl_A > real_B 而不可玩。因此先玩 AA 至少不会比先玩 BB 丢失更多选项,且直接获得更大的 curcur。严格证明可用交换论证:最优解中若第一次未选最大 realreal,可交换两次操作顺序得到不差的结果。故贪心正确。 ∎

    终止性:每次循环要么增加 curcurreali>curreal_i > cur 时严格增加),要么 curcur 不变但堆中元素减少(当 reali=curreal_i = cur 时,该赌场被丢弃)。因为 curcur 有上界 maxri\max r_i,且堆大小有限,算法必然终止。

    最优性:贪心过程模拟了不断选取当前最大 realreal 的可行操作,最终 curcur 达到任何可能序列都无法超越的值(因为任何其他操作顺序得到的 curcur 都会被贪心序列在某个步骤中达到或超过)。

    代码实现(C++)

    #include <bits/stdc++.h>
    using namespace std;
    
    void solve() {
        int n, k;
        cin >> n >> k;
        vector<tuple<int,int,int>> casinos(n);
        for (int i = 0; i < n; ++i) {
            int l, r, real;
            cin >> l >> r >> real;
            casinos[i] = {l, r, real};
        }
        sort(casinos.begin(), casinos.end()); // 按 l 升序
    
        priority_queue<pair<int,int>> pq; // (real, r)
        int cur = k;
        size_t ptr = 0;
        while (true) {
            // 加入所有 l <= cur 的赌场
            while (ptr < n && get<0>(casinos[ptr]) <= cur) {
                pq.push({get<2>(casinos[ptr]), get<1>(casinos[ptr])});
                ++ptr;
            }
            // 移除不可玩的(r < cur)
            while (!pq.empty() && pq.top().second < cur) {
                pq.pop();
            }
            if (pq.empty()) break;
            // 选择 real 最大的
            cur = pq.top().first;
            pq.pop(); // 每个赌场只用一次
        }
        cout << cur << '\n';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) solve();
        return 0;
    }
    • 1

    信息

    ID
    6640
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    1
    已通过
    1
    上传者