优先队列/堆 题目讲解

优先队列/堆 题目讲解

cpp 复制代码
洛谷
P1628
p1334
p1090
p12802
p2278

priority_queue(优先队列/堆)
cpp 复制代码
//大根堆
priority_queue<int> heap;

//小根堆
priority_queue<int,vector<int>,greater<int>> heap;

heap.push(x);//插入一个数x
heap.top();//返回堆顶元素
heap.pop();//弹出堆顶元素

pq.emplace(people[j].r, people[j].idx);等效于pq.push(make_pair(people[j].r, people[j].idx));
在优先队列 pq 中,直接构造一个 pair(r, idx) 对象,

p1628

小根堆读入符合要求的字符串然后依次读,弹就行

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n;
    cin>>n;

    vector<string> a(n);
    for(int i = 0;i<n;i++) cin>>a[i];

    string T;
    cin>>T;

    priority_queue<string,vector<string>,greater<string>> q;

    for(int i = 0;i<n;i++){
        if(a[i].size()>=T.size() && a[i].substr(0,T.size())==T){
            q.push(a[i]);
        }
    }

    while(!q.empty()){
        cout<<q.top()<<"\n";
        q.pop();
    }
}

p1334

倒过来看,等价于不断合并两块木板,合并代价是两块之和,得到代价总和最小,那就贪心思想每次取最小两块合并。同样可以用小根堆解决。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n;
    cin>>n;

    priority_queue<ll,vector<ll>,greater<ll>> q;

    for(int i = 0;i<n;i++){
        ll x;
        cin>>x;
        q.push(x);
    }

    ll ans = 0;

    while(q.size()>1){
        ll a = q.top(); q.pop();
        ll b = q.top(); q.pop();
        ll s = a+b;
        ans += s;
        q.push(s);
    }

    cout<<ans;
}

p1090

这题与上一题本质完美一模一样,甚至代码都不用改的。就是上一题倒过来的思维

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n;
    cin>>n;

    priority_queue<ll,vector<ll>,greater<ll>> q;

    for(int i = 0;i<n;i++){
        ll x;
        cin>>x;
        q.push(x);
    }

    ll ans = 0;

    while(q.size()>1){
        ll a = q.top(); q.pop();
        ll b = q.top(); q.pop();
        ll s = a+b;
        ans += s;
        q.push(s);
    }

    cout<<ans;
}

p12802

也是贪心加优先队列,对于入侵的,肯定优先入侵好打的(人少的)。贪心优先入侵小星球积累资源,再用大根堆动员最大舰队以最少次数征服剩余星球。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int T;
    cin>>T;

    while(T--){
        int n;
        ll k;
        cin>>n>>k;

        vector<ll>a(n);
        ll sum = 0;
        for(int i = 0;i<n;i++){
            cin>>a[i];
            sum += a[i];
        }

        if(k>=sum){
            cout<<0<<"\n";
            continue;
        }

        sort(a.begin(),a.end());

        priority_queue<ll> q;

        ll temp = 0;
        ll ans = 0;
        int p = 0;

        while(1){

            while(p<n && a[p]<=k+temp){
                q.push(a[p]);
                p++;
            }

            if(q.empty()){
                cout<<-1<<"\n";
                break;
            }

            temp += q.top();
            q.pop();
            ans++;

            if(k+2*temp>=sum){
                cout<<ans<<"\n";
                break;
            }
        }
    }
}

p2278

优先队列+臭模拟,跟前面的不同之处在于要自定义一下priority_queue的排序规则

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

struct node{
	int id,st,re,pr;
	bool operator < (const node &a)const{
		if(pr==a.pr) return st>a.st;   // 优先级相同,先到的优先
		else return pr<a.pr;          // 优先级大的优先
	}
};

node c;
long long ti;                     // 当前时间
priority_queue<node> q;           // 等待队列(大根堆)

int main(){
	while(cin>>c.id>>c.st>>c.re>>c.pr){
		
		// 先把当前能在新进程到达前执行完的进程全部跑完
		while(!q.empty() && ti+q.top().re<=c.st){
			node b=q.top(); q.pop();
			cout<<b.id<<" "<<ti+b.re<<endl;  // 输出完成时间
			ti+=b.re;                       // 时间推进
		}
		
		// 若当前进程还没跑完,被新进程抢占
		if(!q.empty()){
			node d=q.top(); q.pop();
			d.re=d.re-(c.st-ti);   // 减去已经执行的时间
			q.push(d);             // 放回等待队列
		}
		
		q.push(c);     // 新进程入队
		ti=c.st;       // 时间跳到新进程到达时刻
	}
	
	// 输入结束后,把剩余进程全部跑完
	while(!q.empty()){
		node f=q.top(); q.pop();
		ti+=f.re;
		cout<<f.id<<" "<<ti<<endl;
	}
	return 0;
}
相关推荐
SamtecChina20231 小时前
Samtec连接器设计研究 | 载流量:温升为什么重要?
大数据·网络·人工智能·算法·计算机外设
shangjian0071 小时前
AI-大语言模型LLM-LangChainV1.0学习笔记-OpenAI类和ChatOpenAI类
人工智能·学习·语言模型
yzx9910131 小时前
从单一到融合:机器学习、多模型学习与大语言模型的全面综述
学习·机器学习·语言模型
程序员南飞1 小时前
排序算法举例
java·开发语言·数据结构·python·算法·排序算法
shangjian0071 小时前
AI-大语言模型LLM-LangChainV1.0学习笔记-模型不同调用方式的差异
人工智能·学习·语言模型
flyyyya1 小时前
【AI学习从零至壹】AI agent自动化工作流
人工智能·学习·自动化
2501_918126911 小时前
stm32是用杜邦线母头接核心板和调试器吗
stm32·单片机·嵌入式硬件·学习·个人开发
adore.9681 小时前
2.24 oj95 96 97
开发语言·c++·算法
白中白121382 小时前
算法题-16
算法