洛谷P12652 [KOI 2024 Round 2] 拔树游戏

题面分析

对于一次“拔除”操作根节点取到的值一定是目前根节点所有儿子中最小的,而下一次“拔除”中根节点取到的值是目前根节点除最小儿子外的所有儿子和最小儿子的所有儿子中最小的那个。

关于具体实现

容易想到小根堆维护,每次取小根堆队头,再将队头节点的所有儿子加入小根堆。

需要注意的是std::priority_queue中的优先队列是大根堆,可以用取权值相反数或重载运算符的方式解决。

Code

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int rd() //快读

const int N = 3e5 + 5;
int n;
int a[N],pre[N];
struct node
{
    int id,val;
    bool operator < (const node &x) const {return val > x.val; }
};

vector<int> adj[N];

signed main()
{
    n = rd();
    for(int i = 2;i <= n;i++) adj[rd()].push_back(i);
    for(int i = 1;i <= n;i++) a[i] = rd();
    priority_queue<node> q;
    q.push({1,a[1]});
    for(int i = 1;i <= n;i++)
    {
        int u = q.top().id;
        cout << q.top().val << '\n';
        q.pop();
        for(auto v : adj[u]) q.push({v,a[v]});
    }
    return 0;
}
posted @ 2025-07-10 17:48  IC0CI  阅读(8)  评论(0)    收藏  举报