看病

GitHub跳转原题关系图返回列表

用大根堆维护排队患者,C++ priority_queue 直接 push / top / pop,每次操作 O(log n),共 O(n log n)。

OJ: roj

题目 ID: 1371

难度:普及-

标签:堆优先队列python

创建: 2026-09-30 07:29

更新: 2026-10-05 12:23

题目描述

医院按病情优先级安排看病。依次处理 nn 个操作:push a b 表示姓名 a、优先级 b 的患者加入排队;pop 表示取出当前排队中优先级最大的患者,输出其姓名和优先级,若无人排队输出 none。所有优先级互不相同。

输入样例 输出样例
pop / push bob 3 / push tom 5 / push ella 1 / pop / push zkw 4 / pop none / tom 5 / zkw 4

数据范围:1⩽n⩽1000001 \leqslant n \leqslant 100000,0⩽0 \leqslant 优先级 ⩽2000000000\leqslant 2000000000,姓名为长度小于 20 的小写字母串。

思路

只有「插入」和「取最大」两种操作,这是优先队列的标志性场景:用大根堆 priority_queue<pair<ll, string> > 维护排队患者,push 入堆,pop 时取堆顶,堆空输出 none。每次堆操作 O(log⁡n)O(\log n),总复杂度 O(nlog⁡n)O(n \log n)。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-30 07:33
# update_at: 2026-09-30 07:33

import sys
from heapq import heappush, heappop


def solve() -> None:
    """用大根堆维护排队患者:pop 输出优先级最大者,空队输出 none。"""
    data = iter(sys.stdin.read().split())
    out: list[str] = []
    heap: list[tuple[int, str]] = []  # 存 (-优先级, 姓名):Python 只有最小堆,优先级取负即变大根堆

    for _ in range(int(next(data))):
        op = next(data)
        if op == "push":
            name, priority = next(data), int(next(data))
            heappush(heap, (-priority, name))  # 优先级互不相同,元组比较不会走到姓名
        elif heap:
            neg_priority, name = heappop(heap)
            out.append(f"{name} {-neg_priority}")
        else:
            out.append("none")

    print('\n'.join(out))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 12:23
 * update_at: 2026-10-05 12:23
 */

#include <cstdio>
#include <queue>
#include <string>
#include <iostream>

using namespace std;

typedef long long ll;

// 大根堆:堆顶是当前排队中优先级最大的患者(pair 先比优先级,再比姓名)
priority_queue< pair<ll, string> > q;

int main() {
    ll n;
    scanf("%lld", &n);

    for (ll i = 1; i <= n; i++) {
        string op;
        cin >> op;
        if (op == "push") {
            string name;
            ll pri;
            cin >> name >> pri;
            q.push(make_pair(pri, name)); // 入队
        } else {
            // pop:输出当前优先级最大的患者
            if (q.empty()) {
                printf("none\n");
            } else {
                cout << q.top().second << " " << q.top().first << endl;
                q.pop();
            }
        }
    }
    return 0;
}