堆及堆的变种

Posted tyner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆及堆的变种相关的知识,希望对你有一定的参考价值。

堆及堆的变种

声明

参考课件和讲授来自Accelerator,分析懒得打也来自他

堆的元素删除

借用标记的思想,我们维护一个和原堆同样性质(大根,小根)的堆,每次删除就把它扔到标记堆里面
当我们需要 pop 的时候,如果堆顶元素和删除堆顶元素相同,
那么就说明这个元素是我们之前删除过的,于是我们就在删除堆里面和这个堆里面同时 pop, 然后考察下一元素。
容易发现时间复杂度和空间复杂度没有什么实质性的变化。

luogu P3545 [POI2012]HUR-Warehouse Store

我们最先想到的是能卖就卖,但是却有可能直接卖给一个人剩下的不够而 GG
为了避免这种情况,我们把已经卖掉的所有价值扔到一个堆里,每次取出堆顶的元素和当前的价值进行比较,如果堆顶的元素比他大,那就“退掉”之前的东西,换给他。
这样虽然不能使答案增加,但是可以增加库存。有一种前人栽树后人乘凉的感觉 233

因为题目没说要按顺序,所以就只用了一个结构体(看题解可以偷懒

#include<cstdio>
#include<queue>
using namespace std;
#define ll long long
const int MAX = 250000+9;

inline ll read() 
    char ch = getchar(); ll f = 1, x = 0;
    while(ch<'0' || ch>'9') if(ch=='-') f = -1; ch = getchar();
    while(ch>='0' && ch<='9') x = x*10+ch-'0'; ch = getchar();
    return x*f;


int n;
ll kucun;

struct time
    ll arr, brr;//这里的arr,在day里面是第i天进货数,在p_q里面是记录的满足了第几天的客人 
    bool operator < (const time& xxx) const 
        return brr < xxx.brr;//大根堆:为了取出前面花费最多的
    
day[MAX];
priority_queue <time> q;


int main() 
    n = read();
    for(int i = 1; i <= n; i++) day[i].arr = read();
    for(int i = 1; i <= n; i++) day[i].brr = read();
    int t = 0;//表示满足了多少人 
    for(int i = 1; i <= n; i++) 
        kucun += day[i].arr;
        if(kucun >= day[i].brr)  //能买就买 
            kucun -= day[i].brr;
            t++;
            time now; now.arr = i, now.brr = day[i].brr;
            q.push(now); 
         else 
            if(q.size() && q.top().brr > day[i].brr) //不能买的时候再“退钱回去” 
                kucun += q.top().brr-day[i].brr;//这波不亏
                q.pop(); 
                time now; now.arr = i, now.brr = day[i].brr;
                q.push(now); 
            
        
    
    printf("%d\n", t);
    while(!q.empty()) printf("%lld ",q.top().arr), q.pop();//里面装的都是满足了的 
    printf("\n");

以上是关于堆及堆的变种的主要内容,如果未能解决你的问题,请参考以下文章

数据结构堆及堆排序详解

用仿函数实现大小堆及堆排序

堆及操作集_mooc

斜堆(待补充)

二叉堆及优先级队列

GAN的基本介绍和变种