[CF1329C] Drazil Likes Heap

[CF1329C] Drazil Likes Heap - 贪心

Description

定义一种堆的删除操作:对节点x操作,相当于从x出发,每次向大儿子走,直到走到叶子节点,删掉叶子节点,把路径上(除x外)每个值都向上移一步,最后把x原本的值覆盖掉。将大顶堆从高度h降低到g,必须应用题中的算法保证它们的和最小,输出和,并且输出被删除操作的序号。

Solution

不断对根节点执行算法删除操作,如果根不能删了(再删就会导致 g 层有空位)就递归处理左右子树

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

#define int long long

const int N = 5000005;

int h, g, a[N];
vector<int> ans, res;

void del(int p)
{
    if (a[p * 2] == 0 && a[p * 2 + 1] == 0)
    {
        a[p] = 0;
        return;
    }
    if (a[p * 2] < a[p * 2 + 1])
    {
        a[p] = a[p * 2 + 1];
        del(p * 2 + 1);
    }
    else
    {
        a[p] = a[p * 2];
        del(p * 2);
    }
}

int get_leaf(int p)
{
    if (a[p * 2] == 0 && a[p * 2 + 1] == 0)
    {
        return p;
    }
    if (a[p * 2] < a[p * 2 + 1])
    {
        return get_leaf(p * 2 + 1);
    }
    else
    {
        return get_leaf(p * 2);
    }
}

void divide(int p)
{
    if (!p)
        return;
    if (p >= (1 << g))
        return;
    while (get_leaf(p) >= (1 << g))
    {
        ans.push_back(p);
        res.push_back(a[p]);
        del(p);
    }
    divide(p * 2);
    divide(p * 2 + 1);
}

void solve()
{
    cin >> h >> g;
    int n = (1 << h) - 1;
    for (int i = 1; i <= 4 * n; i++)
        a[i] = 0;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    int sum = 0;
    for (int i = 1; i <= n; i++)
        sum += a[i];
    divide(1);
    for (auto i : res)
        sum -= i;
    cout << sum << endl;
    for (auto i : ans)
        cout << i << " ";
    cout << endl;
    ans.clear();
    res.clear();
}

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14565169.html