C++ STL 优先队列的应用(priority_queue)

洛谷 P3378 【模板】堆

优先队列基本操作(优先队列的底层数据结构就是堆)。洛谷数据量比较大,用cin输入取消同步流依然会TLE,推荐scanf输入。

#include <bits/stdc++.h>
using namespace std;
int opt,x,n;
priority_queue<int,vector<int>,greater<int> >q;//队列中元素按从小到大排序
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&opt);
        if(opt==1)scanf("%d",&x),q.push(x);
        else if(opt==2)printf("%d\n",q.top());
        else q.pop();
    }
    return 0;
}

nefu 1537 买饭-优先队列

优先队列中放结构体,自定义比较结构体需要重载运算符,功能和sort中的自定义比较函数cmp一样。

#include <bits/stdc++.h>
using namespace std;
int n,x;
struct node
{
    int x,num;
};
bool operator < (const node &s1,const node &s2)//结构体自定义比较,重载运算符
{
    if(s1.x!=s2.x)return s1.x>s2.x;
    return s1.num>s2.num;
}
priority_queue<node,vector<node> >q;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        q.push({x,i});
    }
    double tim=0,ans=0;
    while(!q.empty())
    {
        node tmp=q.top();q.pop();
        ans+=tim;//tim记录当前人的等待时间,ans记录等待时间总和
        tim+=1.0*tmp.x;
        q.empty()?printf("%d\n",tmp.num):printf("%d ",tmp.num);
    }
    printf("%.2lf\n",ans/(1.0*n));
    return 0;
}

洛谷 P1090 合并果子

#include <bits/stdc++.h>
using namespace std;
int n,x,ans;
priority_queue<int,vector<int>,greater<int> >q;//队列中元素按从小到大排序
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        q.push(x);
    }
    while(q.size()>1)
    {
        int t1=q.top();q.pop();
        int t2=q.top();q.pop();
        q.push(t1+t2);
        ans+=t1+t2;
    }
    printf("%d\n",ans);
    return 0;
}

洛谷 P1334 瑞瑞的木板

题意是合并果子的逆过程,本质还是一样的。ans要开long long。

#include <bits/stdc++.h>
using namespace std;
int n,x;
long long ans;
priority_queue<int,vector<int>,greater<int> >q;//队列中元素按从小到大排序
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        q.push(x);
    }
    while(q.size()>1)
    {
        int t1=q.top();q.pop();
        int t2=q.top();q.pop();
        q.push(t1+t2);
        ans+=t1+t2;
    }
    printf("%lld\n",ans);
    return 0;
}

nefu 355 合成陨石-优先队列

上题改成多组输入,记得初始化以及清空队列。

#include <bits/stdc++.h>
using namespace std;
int n,x;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    ios::sync_with_stdio(false);
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            q.push(x);
        }
        int ans=0;//初始化
        while(q.size()>1)
        {
            int t1=q.top();q.pop();
            int t2=q.top();q.pop();
            q.push(t1+t2);
            ans+=t1+t2;
        }
        q.pop();//记得清空队列(最后还剩了一个元素)
        printf("%d\n",ans);
    }
    return 0;
}

洛谷 P1631 序列合并

首先,把A和B两个序列分别从小到大排序,变成两个有序队列。这样,从A和B中各任取一个数相加得到N2个和,可以把这些和看成形成了n个有序表/队列:

A[1]+B[1] <= A[1]+B[2] <= … <= A[1]+B[N]

A[2]+B[1] <= A[2]+B[2] <= … <= A[2]+B[N]

……

A[N]+B[1] <= A[N]+B[2] <= … <= A[N]+B[N]

接下来,就相当于要将这N个有序队列进行合并排序:

首先,将这N个队列中的第一个元素放入一个优先队列中;

然后,每次取出堆中的最小值。若这个最小值来自于第k个队列,那么,就将第k个队列的下一个元素放入堆中。

时间复杂度:O(NlogN)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
int n,a[N],b[N];
struct node
{
    int x,y;
    ll sum;
};
bool operator < (const node &s1,const node &s2)
{return s1.sum>s2.sum;}
priority_queue<node,vector<node> >q;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
        cin>>b[i];
    for(int i=1;i<=n;i++)
        q.push({i,1,a[i]+b[1]});
    for(int i=1;i<=n;i++)
    {
        node tmp=q.top();q.pop();
        i==n?printf("%lld\n",tmp.sum):printf("%lld ",tmp.sum);
        int x=tmp.x,y=tmp.y;
        q.push({x,y+1,a[x]+b[y+1]});
    }
    return 0;
}

nefu 1690 桐桐的新闻系统-优先队列

和序列合并的思想类似。

#include <bits/stdc++.h>
using namespace std;
char s[10];
int k,id,tim;
struct node
{
    int id,tim,sum;//基础时间为tim,sum为tim的倍数(每次增加tim)
};
bool operator < (const node &s1,const node &s2)
{
    if(s1.sum!=s2.sum)return s1.sum>s2.sum;
    return s1.id>s2.id;
}
priority_queue<node,vector<node> >q;
int main()
{
    ios::sync_with_stdio(false);
    while(cin>>s&&s[0]!='#')
    {
        cin>>id>>tim;
        q.push({id,tim,tim});
    }
    cin>>k;
    while(k--)
    {
        node tmp=q.top();q.pop();
        printf("%d\n",tmp.id);
        q.push({tmp.id,tmp.tim,tmp.sum+tmp.tim});//把该id对应的时间sum加上tim
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nefu-ljw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值