优先队列笔记

本文介绍了如何运用priority_queue在四个编程挑战中解决问题,包括HDU 4006、POJ 3253、POJ 2833和POJ 2431。通过小顶堆和大顶堆实现最值查询、哈夫曼树模拟、区间操作及贪心策略,展示了优先队列在解决实际问题中的灵活性和高效性。
摘要由CSDN通过智能技术生成

算法思想

略,可用priority_queue实现

训练

HDU4006

题目大意:n轮,每次可以记录一个数或询问第k大的数是什么,分别对应I c和Q,求每次询问的结果

思路:用优先队列记录当前的前k大的数字即可,用小顶堆

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
int n,k,x;
char ch;
int main() {
    while(~scanf("%d%d",&n,&k)) {
        priority_queue<int,vector<int>,greater<int>>Q;
        while(n--) {
            cin >>ch;
            if(ch=='I') {
                scanf("%d",&x);
                if(Q.size()<k)//如果能存
                    Q.push(x);
                else if(Q.top()<x) {//如果比堆顶小,代表堆顶不为当前第k大的数
                    Q.pop();
                    Q.push(x);
                }
            } else
                printf("%d\n",Q.top());
        }
    }
    return 0;
}

POJ3253

题目大意:N块木板,每块长度为 L i L_i Li,一开始是一整个木板,现在要切成N块,每次费用为切出的木板长度和,求最小费用

思路:用哈夫曼树的思想,使用优先队列模拟完成,注意long long

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
ll N,L,ans;
priority_queue<ll,vector<ll>,greater<ll>>Q;
int main() {
    scanf("%d",&N);
    for(int i=0; i<N; i++) {
        scanf("%lld",&L);
        Q.push(L);
    }
    while(Q.size()!=1) {
        ll t=0;
        t+=Q.top();
        Q.pop();
        t+=Q.top();
        Q.pop();
        Q.push(t);
        ans+=t;
    }
    if(ans==0)
        ans+=Q.top();
    printf("%lld",ans);
    return 0;
}

POJ2833

题目大意:给n个正整数,去掉 n 1 n_1 n1个最大值,去掉 n 2 n_2 n2个最小值,求剩下的平均值

思路:维护一个优先队列来存前 n 1 n_1 n1个最大值和 n 2 n_2 n2个最小值

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
ll n1,n2,n,x;
int main() {
    while(~scanf("%lld%lld%lld",&n1,&n2,&n)&&n1&&n2&&n) {
        priority_queue<ll,vector<ll>,less<ll>>Q2;
        priority_queue<ll,vector<ll>,greater<ll>>Q1;
        ll ans=0;
        for(int i=0; i<n; i++) {
            scanf("%lld",&x);
            if(Q1.size()<n1)
                Q1.push(x);
            else if(Q1.top()<x)
                Q1.pop(),Q1.push(x);
            if(Q2.size()<n2)
                Q2.push(x);
            else if (Q2.top()>x)
                Q2.pop(),Q2.push(x);
            ans+=x;
        }
        while(!Q1.empty()) {
            ans-=Q1.top();
            Q1.pop();
        }
        while(!Q2.empty()) {
            ans-=Q2.top();
            Q2.pop();
        }
        printf("%.6f\n",(double)ans/(n-n1-n2));
    }
    return 0;
}

POJ2431

题目大意:一辆车,走一里一升油,一开始有P升,距目的地L,路上有N个加油站,各自能提供 f i f_i fi升,问到达目的地最少加油次数,不能到达输出-1

思路:贪心+优先队列

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int N,ans,L,P;
typedef struct node {
    int L,P;
    bool operator<(node a)const {
        return L>a.L;
    }
} node;
node power[12121];
int main() {
    scanf("%d",&N);
    for(int i=0; i<N; i++)
        scanf("%d%d",&power[i].L,&power[i].P);
    scanf("%d%d",&L,&P);
    sort(power,power+N);//排序
    priority_queue<int>Q;
    int pos=P,k=0;//pos为当前可到达最远距离
    while(pos<L) {
        while(pos>=L-power[k].L&&k<N)//如果油够用
            Q.push(power[k++].P);
        if(Q.empty()) {
            printf("-1");
            return 0;
        }
        pos+=Q.top();//油不够,加油
        Q.pop();
        ans++;
    }
    printf("%d",ans);
    return 0;
}

总结

优先队列的用法较简单,一般用其性质进行最值的求解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值