关于优先队列的一点细节
主要是关于存储数据的细节
直接上题目:
T1
一名老师希望知道他所在的班级成绩最好的同学的名字和学号。但是他所在的班级,人员调动很频繁,经常有学生转入或转出。因此,他需要你的帮助。
输入格式:
第一行读入一个数n(n≤105)表示有n次人员调动或成绩询问。
接下来n行,每行读入的第一个数o。
若o为0表示老师询问班级里总成绩最高的学生的姓名和学号。
若o为1,则再读入一个正整数id表示新入班的学生学号,再读入一个正整数score表示该学生的总成绩,最后再读入一个字符串name表示该学生的姓名。
若o为2,则再读入一个正整数id(id≤105)表示学号为id的学生离开了班级。若班级内没有这个学生,则忽略这个操作。
输出格式:
当老师询问班级里总成绩最高的学生的姓名和学号时,输出该学生的姓名与学号, 姓名和学号用一个空格隔开。
如果此时班里没有学生,则输出"NO STUDENTS"(输出引号内的部分)。
如果有多人总成绩相同,则输出学号最小的那个学生的信息。
T2
这是一个模板题,用来模拟堆的功能,也可以用priority_queue来实现。
有3种操作,向集合中添加一个数,删除集合中最小的数,询问集合中最小的数是多少。初始时集合为空。
输入格式:
第一行读入一个数n(1≤n≤105)。
第二行到第n+1行,每行读入一个数o表示哪一种操作。
若o=0,则表示询问集合中最小的数是多少。
若o=1,则表示删除集合中最小的数(若集合为空,忽略此次操作即可)。
若o=2,则再读入一个正整数x表示向集合中添加一个数x,x在int类型范围内。
输出格式:
每一个询问输出一行,表示最小的数的值。
若询问时集合为空,则输出"EMPTY!"(引号里面的内容)。
个人观点
两题都可以用优先队列解决
区别在于,T1的相同数据(学生)多次读入而没有pop()删除时,应视为同一个数据,不要重复存储在优先队列中
如学生A连续入班两次,只记录一次
T2的相同数据读入时,必须当做不同对象存储在队列中
如两次读入数字3,队列中应为 3 3
上代码:
T1(3行注释中文为易错点 注释的代码不重要)
#include<bits/stdc++.h> using namespace std; struct student{ int id,sc,i; bool flag; string name; bool operator >(const student s) const{ return (sc>s.sc)||(sc==s.sc&&id<s.id); } bool operator <(const student s) const{ return (sc<s.sc)||(sc==s.sc&&id>s.id); } }stu[100086]; bool flag[100086]; int main(){ priority_queue<student,vector<student>,less<student> > q; int n,o,idd; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&o); if(!o){ while(!q.empty()&&!flag[q.top().id])//每次循环的必要条件:队列非空 q.pop(); if(q.empty()) cout<<"NO STUDENTS"<<endl; else cout<<q.top().name<<" "<<q.top().id<<endl; } //if(!o)中顺序很重要 如果在while中把队列清空,还需要再输出 NO STUDENTS else if(o==1){ scanf("%d %d",&stu[i].id,&stu[i].sc); cin>>stu[i].name; flag[stu[i].id]=1; // stu[i].flag=0; // stu[i].i=i; q.push(stu[i]); } else if(o==2){ scanf("%d",&idd); flag[idd]=0;//id与i不同!!! // stu[idd].flag=1; // q.push(stu[idd]); // cout<<q.top().id<<" "<<q.top().name<<" "<<q.top().flag<<endl; } } return 0; }
T2
#include<bits/stdc++.h> using namespace std; int main(){ priority_queue<int,vector<int>,greater<int> > pq; int n,tmp,m; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&tmp); if(!tmp){ if(pq.empty()) printf("EMPTY!\n"); else printf("%d\n",pq.top()); } else if(tmp==1){ if(!pq.empty()) pq.pop(); } else if(tmp==2){ scanf("%d",&m); pq.push(m); } } return 0; }
以上。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现