文章目录

    • 队列的定义
      • 队列的基本操作
        • 周末舞会
        • 取纸牌游戏
        • 海港(NOIP2016普及组真题)
        • Blash数集-队列-set
    • 优先队列
      • 优先队列的定义
      • 优先队列的定义方法
      • 用结构体定义优先队列(重载函数)
        • 合并果子-优先队列
        • 桐桐的新闻系统-优先队列
    • 序列合并-优先队列

疫情影响,导致我们宅在家里无(feng)所(kuang)事(bu)事(fan),但是一条消息终止了我们的行为

于是我们又迎来了一轮培训。
首先花了两天时间学习了队列和优先队列,并且做了相应的习题。

队列的定义

队列就是允许在一端进行插入,在另一端进行删 除的线性表。允许插入的一端称为队尾,通常用一个 队尾指针r指向队尾元素,即r总是指向最后被插入的 元素;允许删除的一端称为队首,通常也用一个队首 指针f指向排头元素的前面。初始时f=r=0。

队列的基本操作

(1)初始化队列 queuevis,定义一个队列
(2)入队 vis.push(x)
(3)出队 vis.pop()
(4)判断队列是否为空 vis.empty()
(5)判断队列中元素的数量vis.size()
(6)得到队列的队首元素 vis.front()
综上: #include
用<bits/stdc++.h>则无需考虑头文件。

那么先来一道简单的例题。

周末舞会

假设在周末舞会上,男士们和女士们进入舞厅时,各自排 成一队。跳舞开始时,依次从男队和女队的队头上各出一人 配成舞伴。规定每个舞曲能有一对跳舞者。若两队初始人数 不相同,则较长的那一队中未配对者等待下一轮舞曲。现要 求写一个程序,模拟上述舞伴配对问题。
Input
第 1 行两个正整数,表示男士人数 m 和女士人数 n,1≤m,n≤1000;
第 2 行一个正整数,表示舞曲的数目 k,k≤1000。
Output
共 k 行,每行两个数,之间用一个空格隔开,表示配对舞伴的序号,男士在前,女士在后。
Sample Input
2 4
6
Sample Output
1 1
2 2
1 3
2 4
1 1
2 2

分析:设计两个队列分别存放男士和女士。每对跳舞 的人一旦跳完后就回到队尾等待下次被选。

queue<int>vis1,vis2;
int main()
{int n,m,k,s1,s2;cin>>n>>m;cin>>k;for(int i=1;i<=n;i++) vis1.push(i);for(int i=1;i<=m;i++) vis2.push(i);for(int i=1;i<=k;i++){ s1=vis1.front(); vis1.pop(); vis1.push(s1); //取出对首,并将其放在队尾s2=vis2.front(); vis2.pop(); vis2.push(s2);   //同上cout<<s1<<" "<<s2<<endl;}

如果用数组来实现队列

const int maxn=1000;
int queue[maxn],counter=0,front=0,back=-1 ;
void push(int x)
{queue[++back]=x;++counter;}
int pop()
{--counter; return queue[front++];}

可能会越界,要关注maxn值的范围,推荐使用queue!

那么,再来一道例题

取纸牌游戏

小明正在使用一堆共 K 张纸牌与 N-1 个朋友玩取牌游戏。其中, N≤K≤100000,2≤N≤100,K 是 N 的倍数。纸牌中包含 M=K/N 张 “good”牌和 K-M 张“bad”牌。小明负责发牌,他当然想自己获得所有 “good”牌。
他的朋友怀疑他会欺骗,所以他们给出以下一些限制,以防小明耍诈:
1)游戏开始时,将最上面的牌发给小明右手边的人。
2)每发完一张牌,他必须将接下来的 P 张牌(1≤P≤10)一张一张地依 次移到最后,放在牌堆的底部。
3)以逆时针方向,连续给每位玩家发牌。
小明迫切想赢,请你帮助他算出所有“good”牌放置的位置,以便他得到所 有“good”牌。牌从上往下依次标注为 #1,#2,#3,…
Input
第 1 行,3 个用一个空格间隔的正整数 N、K 和 P。
Output
M 行,从顶部按升序依次输出“good”牌的位置。(就是从小到大输出)
Sample Input
3 9 2
Sample Output
3
7
8

解题思路:
发现“good”的牌都发给了小明自己,根据题目描述的N的倍数都发給了小明自己,所以当K 是N的倍数时,就存入到一个数组当中去。对于这个P要格外注意,当剩余的牌的个数小于P的时候也要 P次。
例如: p=3;
还剩下的编号为4和5;
第1次翻:5 4;
第2次翻:4 5;
第3次翻:5 4;
也是要翻3次的,哪怕就省下1张牌了,也要翻P次!

#include <bits/stdc++.h>
using namespace std;
int a[100005];
queue<int>vis;
int main()
{int n,k,p,num=0,z=0;cin>>n>>k>>p;for(int i=1;i<=k;i++)vis.push(i);while(!vis.empty()){int tmp=vis.front();vis.pop();num++;if(!(num%n))   //如果是n的倍数,则计数a[z++]=tmp;if(!vis.empty())for(int i=0;i<p;i++){  //移动p次牌tmp=vis.front();vis.pop();vis.push(tmp);}}sort(a,a+k/n);for(int i=0;i<k/n;i++)cout<<a[i]<<endl;return 0;
}
海港(NOIP2016普及组真题)

小K是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客。
小K对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况;对于第i艘到达的船,他记录了这艘船到达的时间ti (单位:秒),船上的乘客数k,以及每名乘客的国籍x1,x2,x3,x4等;
小K 统计了这N 艘船的信息,希望你帮助计算出每1艘船到达为止的24小时(86400秒)内到达的船上的乘客来自多少个国家?
Input
第1行为一个n,表示有n条船;
接下来有n行,每行前2个数为t和k,表示这艘船的到达时间和船上的旅客数量!
然后是这k个旅客的国籍(x1 x2 x3 …都是整数)
Output
输出n行,每行代表这艘船到达为止的24小时(86400秒)内到达的船上的乘客来自多少个国家?
t[i]-t[p]<=86400,t[i]表示当前船的时间,t[p]表示之前进海港的船!
1<=n,k<=300000; 1<=ti<=1000000000;
Sample Input
例子输入1:
3
1 4 4 1 2 2
2 2 2 3
10 1 3
例子输入2:
4
1 4 1 2 2 3
3 2 2 3
86401 2 3 4
86402 1 5
Sample Output
例子输出1:
3
4
4
例子输出2:
3
3
3
4

考虑用队列就可以,把每个乘客都分别以结构体的形式即进 入队列(是每一个乘客),结构体{时间,国籍},然后使用 桶排序的思想记录就可以了, 也可以用map来代替桶排序! 当一艘船进入海港时,先压入队列(每个人); 然后在从队 列头开始检查是否满足条件(出栈时计算总的国籍数是否变 化)
struct sa {
int t;//进港时间
int x;//国家
};
本题的难点就在于如何存储本题的数据,把每个人分别入队列就解决了船的问题,有点不好想。
难点:num[x]是桶排序的数组,ans是国家的数量。
1、根据num[x]==0 来判断是增加或减少一个国家。
2、每次新来的船,都先入队列,并统计国家数。
3、用刚新来船的时间和队列头部的船只时间进行比较
4、时间大于等于86400,就出队列,并计算国家数。
5、输出当前的国家数。

#include <bits/stdc++.h>
using namespace std;
struct peo{int t;int x;
};
queue<peo>vis;
int n,t,k,x,ans=0;
int num[100005];
int main()
{ios::sync_with_stdio(0);struct peo tmp;cin>>n;for(int i=0;i<n;i++){cin>>t>>k;for(int j=0;j<k;j++){cin>>x;vis.push({t,x});if(!num[x]) ans++;num[x]++;}while(t-vis.front().t>=86400){tmp=vis.front();vis.pop();int x1=tmp.x;num[x1]--;if(!num[x1]) ans--;}cout<<ans<<endl;}return 0;
}
Blash数集-队列-set

大数学家高斯小时候偶然间发现一种有趣的自然数集合 Blash ,对应以 a 为基的集合 Ba 定义如下:
(1)a 是集合 Ba 的基,且 a 是 Ba 的第一个元素。
(2)如果 x 在集合 Ba 中,则 2x+1 和 3x+1 也都在集合 Ba 中。
(3)没有其他元素在集合 Ba 中了。
现在小高斯想知道如果将集合 Ba 中元素按照升序排列,第 n 个元素会是多少?
Input
一行输入包括两个数字,集合的基 a 以及所求元素序号 n 。(1<=a<=50,1<=n<=100000)
Output
输出第n个元素的值!
Sample Input
1 100
Sample Output
418
Hint
样例2:
输入: 28 5437
输出:900585

#include <bits/stdc++.h>
using namespace std;
int a,n,m[1000005],t2,t3,t,jie;
int main()
{cin>>a>>n;m[1]=a;t2=t3=1;jie=2;while(jie<=n)       //求取第n小的数{int x2,x3;x2=m[t2]*2+1;     //2x+1在数集中x3=m[t3]*3+1;      //3x+1在数集中t=min(x2,x3);       //取x2,x3的较小值if(x2>x3)            //哪一方较小,就下标+1t3++;elset2++;if(m[jie-1]!=t)        //去重,如果t与前一个数相同,则不用放入数组m[jie++]=t;}cout<<m[n]<<endl;return 0;
}

这道题也可以使用set+queue做,set用来去重


优先队列

优先队列的定义

priority_queue翻译为优先队列,一般用来解决一些贪心问题,其底层是用“堆”来实现的。在优先队列中,任何时刻,队首元素一定是当前队列中优先级最高(优先值最大) 的那一个(大根堆),也可以是最小的那一个(小根堆)。 可以不断往优先队列中添加某个优先级的元素,也可以不断弹出优先级最高的那个元素,每次操作其会自动调整结构, 始终保证队首元素的优先级最高。

优先队列的定义方法

定义和使用priority_queue前,要添加queue头文件。
定义一个priority_queue的方法为: priority_queue< type > name;//type通常为结构体
其中,type可以是任何基本类型或者容器,name为优先队列的名字。
和queue不一样的是,priority_queue没有front()和back(),而只能通过top()或pop()访问队首元素(也称堆顶元素),也就是优先级最高的元素。
大根堆:从大到小排列。
小根堆:从小到大排列。
优先队列就是堆,也可以自己手写堆。
//小根堆的写法 priority_queue<int,vector< int >,greater< int > > vis;
//大根堆的写法 priority_queue<int,vector< int >,less< int > > vis;
当就是1个类型,可以这样直接写; 也可以用结构题

用结构体定义优先队列(重载函数)

typedef long long LL;
struct sa {
LL x;
LL y;
LL sum;
};
LL a[400005],b[400005];
bool operator < (const sa &a,const sa &b)
{
return a.sum >b.sum;//表示的是从小到大
}

合并果子-优先队列

Description
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n-1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 1 ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有 3 种果子,数目依次为 1 , 2 , 9 。可以先将 1 、 2 堆合并,新堆数目为 3 ,耗费体力为 3 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12 ,耗费体力为 12 。所以多多总共耗费体力 =3+12=15 。可以证明 15 为最小的体力耗费值。
Input
共两行。
第一行是一个整数 n(1≤n≤10000) ,表示果子的种类数。
第二行包含 n 个整数,用空格分隔,第 i 个整数 ai(1≤ai ≤20000) 是第 i 种果子的数目。
Output
一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2^31。
Sample Input
3
1 2 9
Sample Output
15

分析:
每次取2个数出来,合并后的数再压入优先队列!
再用1个变量累加记录每次取2个数的和!
队列:1 2 9
1+2=3; 把3压入队列;ans+=3;
队列:3 9
3+9=12;
ans+=12; 答案=15;如果队列为空就不放元素了!

#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(0);cin>>n;for(int i=0;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;}cout<<ans<<endl;return 0;
}
桐桐的新闻系统-优先队列

Description
桐桐为期末的计算机作业设计了一套新闻系统,他把这套系统称为Argus;
使用这套系统的用户可以向这套系统注册,然后这套系统就会以用户要求发送新闻的时间间隔向用户发送一次新闻。向Argus注册的指令具有以下格式:
Register Q_num Period
Q_num(0 < Q_num<=3000)是用户的ID,Period(0 < Period <= 3000)是间隔。注册后Period秒,结果会第一次到达。所有的用户都有不同的Q_num。桐桐测试了一段时间后,想知道系统前K次给谁发送新闻了。如果同一时间发送多个新闻,以Q_num的升序排列。
Input
第一部分是注册指令,每条一行。指令数不超过1000,所有人指令同时执行完。此部分以“#”结束。
第二部分仅一行一个正整K,K<=10000
Output
输出前K个新闻发送到的用户的Q_num,每行一个。
Sample Input
Register 2004 200
Register 2005 300

5
Sample Output
2004
2005
2004
2004
2005

构造一个结构体
struct node{
int num,tim,sum;
} ;
tim是间隔时间,sum是总共的时间
这样先把所有的用户输入,再进行排序
一个用户被弹出队列后,将sum+=tim后,在插进队列里

#include <bits/stdc++.h>
using namespace std;
struct node{int num,tim,sum;
} ;
char a[10];
bool operator < (const node &s1,const node &s2)
{if(s1.sum!=s2.sum) return s1.sum>s2.sum;   //先按sum从小到大排序return s1.num>s2.num;                       //再按num从小到大排序
}
int num,tim,k;
priority_queue<node,vector<node> >q;
int main()
{node tmp;ios::sync_with_stdio(0);while(cin>>a,a[0]!='#'){cin>>num>>tim;tmp.num=num;tmp.tim=tim;tmp.sum=tim;q.push(tmp);}cin>>k;while(k--){tmp=q.top();q.pop();cout<<tmp.num<<endl;  //输出numtmp.sum+=tmp.tim;q.push(tmp);          //重新插入队列}return 0;
}
序列合并-优先队列

Description
给出两个长度为 n 的有序表 A 和 B,在 A 和 B 中各任取一个元素,可以得到 n^ 2 个和,求这些和中最小的 n 个。
Input
第 1 行包含 1 个整数 n(1≤n≤400000)。
第 2 行与第 3 行分别有 n 个整数,各代表有序表 A 和 B。一行中的每两个整数之间用一个空格隔开,大小在长整型范围内,数据保证有序表单调递增。
建议用scanf()读入,否则会TLE!
Output
输出共 n 行,每行一个整数,第 i 行为第 i 小的和。
数据保证在 long long 范围内。
Sample Input
3
2 6 6
1 4 8
Sample Output
3
6
7

分析:
如果把n·n个数都算出来,一定会TLE
那么只能考察优化的方法,如何把前n个数放进去,也就是位置的先后入队列的顺序。
本题时间卡的很紧,用快读也没快多少,还是scanf()的好!
本题主要的思路,在纸上自己计算一下,先把第一行的和入优先队列, 然后从第2行的和开始,每出队列1个和就把这个位置下方的和压入队列!
例如坐标<1,1>的和出队列,就把坐标<2,1>的和压入队列

#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(0);node tmp;cin>>n;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++) cin>>b[i];tmp.y=0;for(int i=0;i<n;i++) tmp.x=i,tmp.sum=a[i]+b[0],q.push(tmp);for(int i=0;i<n;i++){tmp=q.top();q.pop();printf("%lld\n",tmp.sum);tmp.y++;tmp.sum=a[tmp.x]+b[tmp.y];q.push(tmp);}return 0;
}

大一寒假培训(七)——队列与优先队列相关推荐

  1. 大一寒假培训(三)——暴力枚举及妙用

    大一寒假培训(三) 经过两天的培训之后,第三天也到来了.今天讲的是暴力枚举.好像没什么可讲的(悄咪咪地说) 接下来还是今天的练习 nefu 8 二倍的问题 Description 给定2到15个不同的 ...

  2. 大一寒假培训(二)——快排与桶排

    大一寒假培训(二) 今天是寒假培训的第二天,今天学了快排和桶排.以下是今天做的习题. nefu 1481 谁考了第k名-排序 Description 在一次考试中,每个学生的成绩都不相同,现知道了每个 ...

  3. NEFU 大一寒假培训【一】二维数组、结构体

    主题:二维数组.结构体 A 二维矩阵对角线和 Description 计算m×m的方阵的对角线所有元素的和 Input 输入数据有多组,每组第1行为m (2<=m<=10),接下来有m行m ...

  4. 2020大一寒假培训三 (暴力)

    比例简化 Problem:J Time Limit:1000ms Memory Limit:65535K Description 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果.例如 ...

  5. 大一寒假训练:集训内容考试(二)【未完待续】

    一.前情提要 在经过三天的摸鱼 学习写bug队列.优先队列和素数筛相关内容之后,参加集训的同学们终于迎来了第二场考试,在这场考试中,我会有哪些脑残操作进步呢? 总结: 1.用scanf多组输入再一次忘 ...

  6. java先进先出 循环队列,JavaScript队列、优先队列与循环队列

    队列是一种遵从先进先出(FIFO)原则的有序集合 队列在尾部添加新元素,从顶部移除元素 队列的理解 队列在我们生活中最常见的场景就是排队了 队列这个名字也已经很通俗易懂了 和栈很像,这不过队列是先入先 ...

  7. NEFU 大一寒假训练十二(set)2020.02.18

    Summary 可能是昨天的题少了一些,今天的题多了一堆,还疯狂TLE /(ㄒoㄒ)\~~ Information No. Title AC/Submit A 明明的随机数-set 60/101 B ...

  8. 大一寒假集训(11)(12)---map,set

    大一寒假集训(11)-map 1.查字典 nefu 1678 #include <bits/stdc++.h> using namespace std; map<string,int ...

  9. 计算机专业、物联网工程大一寒假规划必备篇

    物联网工程专业大一寒假规划必备篇 1.我这里主推学<<数据结构>> 2.选择一门编程语言来学习,Python.Java.C++.html+css+js 3.想学机器学习. 4. ...

最新文章

  1. 单点登陆的技术实现机制
  2. Gym - 101981I-MagicPotion-最大流
  3. linux 内存管理优化,Linux性能优化实战 内存篇 阅读笔记
  4. 途观l怎么使用_官宣!中型SUV质量最新排名出炉:汉兰达失前三,大众途观L上榜!...
  5. c#怎么设置一个字符串中某个字符的颜色
  6. hive 操作(五)——常用内置函数
  7. Exchange2010安装配置篇二 自动安装
  8. 奇异值分解(SVD) 的 几何意义
  9. 计算机学院姚茜,武汉理工大学第三届届学位评定委员会
  10. SpeedFan 控制风扇转速
  11. 网络神偷 v7.6 免费
  12. web第三课html课堂笔记
  13. 【量化课堂】彼得·林奇的成功投资
  14. 【GD32F310开发板试用】利用I2C接口通过温湿度传感器HDC1080读取当前环境温湿度
  15. java 跳过法定节假日和双休
  16. 2022年Java秋招面试必看的 | Linux 面试题
  17. springboot项目导入idea中环境配置相关问题解决
  18. UltraISO(软碟通)制作U盘启动安装CentOS 7
  19. 梯形波的傅里叶级数分解
  20. 基于VB的COM编程入门教程

热门文章

  1. 爬虫入门教程⑧— BeautifulSoup解析豆瓣即将上映的电影信息
  2. Python编程——pickle模块的使用详解(附实例)
  3. _pickle.UnpicklingError: pickle data was truncated
  4. Google Voice 保留号码
  5. 使用keytool生成SSL证书
  6. Ubuntu中搜狗输入法安装和卸载
  7. 信息化及计算机相关岗位职责,关于印发《信息化管理工作人员岗位职责》的通知...
  8. 基于cp-abe算法的访问控制方法在linux下的实现和算法优化,基于CP-ABE的访问控制研究...
  9. Steam教育在人文研究领域体现的综合素养
  10. 扔鸡蛋问题 动态规划大法