STL综合
一、数据结构
1. 队列
功能 | 代码 |
---|---|
定义 | queue<tp>q |
入队 | .push(x) |
出队 | .pop() |
队头 | .front() |
队尾 | .back() |
为空 | .empty() |
大小 | .size() |
2. 映射
功能 | 代码 |
---|---|
定义 | map<tp1,tp2>name |
增/改 | mp[key]=value |
删除 | .erase(key) |
全删 | .clear() |
头部 | .begin() |
尾部 | .end() |
key 出现 |
.count(key) |
为空 | .empty() |
大小 | .size() |
查找 | .find(key) |
键 | it->first |
值 | it->second |
二、队列例题
1. 约瑟夫环(数据加强)
题目描述
n n n 个人报数,报到 m m m 的人出列,再由下一个人重新从 1 1 1 开始报数,以此类推,输出依次出圈人的编号。
输入描述
一行两个整数 n , m n,m n,m。
输出描述
一行 n n n 个整数,相邻整数用一个空格隔开,按顺序输出每个出圈人的编号
样例1
输入
10 3
输出
3 6 9 2 7 1 8 5 10 4
提示
对于 50 % 50\% 50% 的数据, n , m ≤ 50 n,m\le 50 n,m≤50
对于 80 % 80\% 80% 的数据, n ≤ 1000 , m ≤ 1 0 6 n\le1000,m\le10^6 n≤1000,m≤106
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 5000 , 1 ≤ m ≤ 1 0 9 1\le n\le5000,1\le m\le10^9 1≤n≤5000,1≤m≤109
程序1: 暴力
#include<bits/stdc++.h>
using namespace std;
int n,m;
queue<int>q;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
q.push(i);
for(int i=1;i<=n;i++){
//一共有n个人需要出圈
for(int j=1;j<=m-1;j++){
//前1~m-1的人不用出圈
q.push(q.front());//备份一份本体到队尾
q.pop();//本体删除
}
cout<<q.front()<<" ";//输出出圈人
q.pop();//出圈人出圈
}
return 0;
}
问题:直接模拟会非常耗时,尤其是 m > n m>n m>n 的时候,可以考虑使用模运算作答。
参考答案
#include<bits/stdc++.h>
using namespace std;
int n,m;
queue<int>q;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
q.push(i);
for(int i=1;i<=n;i++){
for(int j=1;j<=(m-1)%q.size();j++){
//模运算,记得不要直接m%=n
q.push(q.front());
q.pop();
}
cout<<q.front()<<" ";
q.pop();
}
return 0;
}
2. 打印队列
题目描述
学生会里只有一台打印机,但是有很多文件需要打印,因此打印任务不可避免地需要等待。有些打印任务比较急,有些不那么急,所以每个任务都有一个 1 ∼ 9 1∼9 1∼9 间的优先级,优先级越高表示任务越急。
打印机的运作方式如下:首先从打印队列里取出一个任务 J J J,如果队列里有比 J J J 更急的任务,则直接把 J J J 放到打印队列尾部,否则打印任务 J J J(此时不会把它放回打印队列)。
给定打印队列中各个任务的优先级,以及所关注的任务在队列中的位置(队首位置为 0 0 0),求该任务完成的时刻。所有任务都需要 1 1 1 分钟打印。
例如,打印队列为 { 1 , 1 , 9 , 1 , 1 , 1 } \{ 1,1,9,1,1,1 \} { 1,</