蓝桥杯历年省赛真题
点击链接免费加入题单
STL
map及其函数
map<key,value>
提供一对一的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。map 中的第一个值称为关键字(key),每个关键字只能在 map 中出现一次,第二个称为该关键字的值(value),可以重复。
// 定义,以 string, int 对为例
#include <map>
map<string, int> mp; // 底层是红黑树,元素可比较大小,key 的结构体要重载 < 运算
// 2- 插入
mp.insert(make_pair("zhs", 18)); // 插入一个键值对,若原先存在该 key,则无法插入和覆盖
mp.insert(pair<string,int>("zhs", 18)); // 插入一个键值对,若原先存在该 key,则无法插入和覆盖
mp["zhs"] = 18; // 甚至可以类似数组下标去访问 key 对应的 value,若原先不存在该 key,则创建,若原先存在,则覆盖以前该关键字对应的值
mp.emplace("zhs", 18); // 插入效果跟 insert 效果完全一样
// 3- 删除
mp.erase(key); // 删除值为 key 的元素
mp.erase(iter); // 删除迭代器 iter 指向的元素,例如 mp.erase(mp.begin());
mp.erase(iter1, iter2); // 删除区间 [iter1, iter2) 的所有元素,例如 mp.erase(mp.begin(), mp.end());
mp.clear(); // 清空集合
// 3- 求大小
int siz = mp.size(); // 求集合大小
bool flag = mp.empty(); // 集合判空
// 4-查询
if(mp.find(key) != mp.end()) // find 函数返回一个指向被查找到元素的迭代器
cout << mp[key] << endl;
if(mp.count(key)) // count 返回某个值元素的个数
cout << mp[key] << endl;
auto iter = mp.lower_bound(key); // 求 key 的下界,返回指向大于等于某值的第一个元素的迭代器
auto iter = mp.upper_bound(key); // 求 key 的上界,返回大于某个值元素的迭代器
// 5-遍历
map<string, int>::iterator iter; // 正向遍历
for(iter=mp.begin(); iter!=mp.end(); iter++)
{
cout << iter->first << " " << iter->second << endl;
// 或者
cout << (*iter).first << " " << (*iter).second << endl;
}
map<int>::reverse_iterator riter; // 反向遍历
for(riter=mp.rbegin(); riter!=mp.rend(); riter++)
{
// 遍历的同时修改
iter->second += 10;
cout << iter->first << " " << iter->second << endl;
}
for (auto x : mp){ // C++ 11 auto 遍历
cout << x.first << " " << x.second << endl;
}
for (auto& x : mp){ // C++ 11 auto 遍历
x.second += 10; // 遍历并修改
cout << x.first << " " << x.second << endl;
}
// 6- 求最值
map<string, int>::iterator it = mp.begin(); // 最小值
cout << *it << endl;
map<string, int>::iterator it = mp.end(); // 最大值
cout << *(--it) << endl;
/*
1. map 和 set 一样,其中的元素必须支持 < 运算符
2. 在插入时,使用 insert 和 用数组方式去插入,在原先存在要插入的键值时是有区别的,insert不会插入,用数组方式插入则会直接覆盖原先数据
3. map 的迭代器支持 ++、--、==、!=、(*iter).first、 (*iter).second、iter->first、 iter->second 等操作
4. map 的迭代器不支持 +、-、 +=、-= 等算术操作符,也不支持 >、<、>=、<= 等比较操作符
*/
map的插入与遍历
#include<bits/stdc++.h>
using namespace std;
map<string,int> m;
int main(){
int n,age;
string s;
cin >> n;
for(int i = 1;i <= n;i++){
cin >> s >> age;
m[s] = age;
}
map<string,int>::iterator it;
for(it = m.begin();it != m.end();it++){
cout << it->first<< " "<< it->second<<endl;
}
}
map的查询
#include<bits/stdc++.h>
using namespace std;
map<string,string> ma;
pair<string,string> p;
int main(){
int m,n,a;
string s,t,str;
set<string,string>::iterator it;
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> s >> t;
p.first = s;
p.second = t;
ma.insert(p);
}
for(int i=1;i<=m;i++){
cin >> a>> str;
if(a==1){
if(ma.find(str)!=ma.end()){
cout << ma[str];
}else{
cout << "NO";
}
}
if(a==2){
if(str <= (ma.begin()->first))
{
cout<<"NO";
}
else{
auto it = ma.lower_bound(str);
it--;
cout<< it->second;
}
}
if(a==3){
if(str >= ((--ma.end())->first))
{
cout<<"NO";
}
else{
auto it = ma.upper_bound(str);
cout<<it->second;
}
}
cout << endl;
}
}
set及其函数
set 的含义是集合,它是一个 有序 的容器,里面的元素都是排序好的,支持插入、删除、查找等操作,就像一个集合。所有的操作的都是严格在 O ( l o g n ) O(logn) O(logn) 时间之内完成,效率非常高。 set 和 multiset 的区别是:set插入的元素不能相同,但是 multiset 可以相同。
// 1- 定义
#include <set>
set<int> s; // 元素必须可比较大小,元素类型必须要支持 < 运算,结构体需要重载 <
// 2- 插入
s.insert(key); // 插入
// 3- 删除
s.erase(key); // 删除值为 key 的元素
s.erase(iter); // 删除迭代器 iter 指向的元素,例如 s.erase(s.begin());
s.erase(iter1, iter2); // 删除区间 [iter1, iter2) 的所有元素,例如 s.erase(s.begin(), s.end());
s.clear(); // 清空集合
// 4- 求大小
int siz = s.size(); // 求集合大小
bool flag = s.empty(); // 集合判空
// 5-查询
if(s.find(key) != s.end()) // find 函数返回一个指向被查找到元素的迭代器
cout << "exist" << endl;
if(s.count(key) == 1) // count 返回某个值元素的个数
cout << "exist" << endl;
set<int>::iterator iter = s.lower_bound(key); // 求 key 的下界,返回指向大于等于某值的第一个元素的迭代器
set<int>::iterator iter = s.upper_bound(key); // 求 key 的上界,返回大于某个值元素的迭代器
// auto 类型推断关键字 在NOI 系列比赛中也可以使用了
auto iter = s.lower_bound(key); // 求 key 的下界,返回指向大于等于某值的第一个元素的迭代器
auto iter = s.upper_bound(key); // 求 key 的上界,返回大于某个值元素的迭代器
// 6-遍历
set<int>::iterator iter; // 正向遍历
for(iter=s.begin(); iter!=s.end(); iter++)
{
cout<<*iter<<endl;
}
set<int>::reverse_iterator riter; // 反向遍历,不重要
for(riter=s.rbegin(); riter!=s.rend(); riter++)
{
cout<<*riter<<endl;
}
// 7- 求最值
set<int>::iterator it = s.begin(); // 最小值
cout << *it << endl;
set<int>::iterator it = s.end(); // 最大值
cout << *(--it) << endl;
/*
注意:
1. set 和优先队列一样,其中的元素必须支持 < 运算符
2. set 的迭代器支持 ++、--、==、!=、*iter 等操作
3. set 的迭代器不支持 +、-、 +=、-= 等算术操作符,也不支持 >、<、>=、<= 等比较操作符
*/
set的插入与遍历
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int> s;//set可以自动去重和排序,默认升序
int n,t;
cin >> n;
for(int i=1;i<=n;i++){
cin >> t;
s.insert(t);//set没有push_back操作
}
set<int>::iterator it;//set需要使用迭代器遍历数据
for(it=s.begin();it!=s.end();it++){//set支持双向迭代器
cout << *it << " ";
}
}
set的查询
#include<bits/stdc++.h>
using namespace std;
int n, m, c, x;
set<int>a;
set <int, greater<int>> b;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int t;
cin >> t;
a.insert(t);
b.insert(t);
}
for (int i = 1; i <= m; i++) {
cin >> c >> x;
if (c == 1) {
if (a.find(x) != a.end())cout << x << "\n";
else cout << "NO\n";
}
if (c == 2) {
set<int>::iterator it;
it = b.upper_bound(x);//二分查找,找第一个大于x的数的地址
if (it != b.end()) {
cout << *it << "\n";
} else cout << "NO\n";
}
if (c == 3) {
set<int>::iterator it;
it = a.upper_bound(x);
if (it != a.end()) {
cout << *it << "\n";
} else cout << "NO\n";
}
}
}
priority_queue优先队列
因为堆的作用主要是用来获取最大/最小值,类似队列的取最值操作,因此堆有一个别名叫优先队列。在 STL 中提供了"优先队列“的模板,即 priority_queue
。关于优先队列具体的应用会在二叉堆与对顶堆中详细讲解。
- 常见使用
#include <queue>
using namespace std;
// using std::priority_queue;
priority_queue<int> q; // 定义一个空的优先队列,默认是大根堆
void test()
{
int x = 5;
q.push(x); // 将 5 插入堆,这时堆顶是 5
q.push(3); // 将 3 插入堆,这时堆顶是 5
q.push(2*x); // 将 10 插入堆,这时堆顶是 10
int k = q.top(); // 取堆顶元素,应该是 10
q.pop(); // 删除堆顶元素,删除了 10,这时堆顶为 5
int s = q.size();// 求堆中元素个数,应为 2
// 清空优先队列的一种方法
while(!q.empty())
q.pop();
// 清空优先队列的第二种方法
q = priority_queue<int>();
}
- 实现小根堆
// 大根堆改成小根堆,其中 vector<Type> 为内部存储容器,greater<Type> 为比较方式
priority_queue<Type,vector<Type>,greater<Type>> q;
// 常为 int 类型
priority_queue<int,vector<int>,greater<int>> q;
- 优先队列与结构体重载运算符
// 只能用于大根堆的结构体
struct node{
int val;
string info;
...
// 大根堆,重载小于运算符
bool operator <(const node& other) const {
return val < other.val;
}
};
// 定义一个大根堆(默认)
priority_queue<node> q;
// 只能用于小根堆的结构体
struct node{
int val;
string info;
...
// 小根堆,重载大于运算符
bool operator >(const node& other) const {
return val > other.val;
}
};
// 定义一个小根堆(默认)
priority_queue<node,vector<node>,greater<node>> q;
pair
将两个变量成对组合打包在一起的数据类型,可以理解为C++内置的保存两个元素(类型可以自定义)的结构体常见的应用就是保存坐标等
pair 支持比较运算符。其比较规则是:先比较第一个元素,如果第一个元素值相等,再比较第二个元素。
pair<int,int> pos;
pos.first = 1;
pos.second = 1;
a = make_pair(1,1);
a = pair<int,int>(1,1);
vector及其函数
vector插入
#include<bits/stdc++.h>
using namespace std;
int a[15];
int main(){
int n,x,y;
cin >> n ;
for(int i=1;i<=n;i++){
cin >> a[i];
}
cin >> x >> y;
vector<int> v(a+1,a+n+1);
v.insert(v.begin()+x-1,y);
for(int i=0;i<v.size();i++){
cout << v[i] << endl;
}
}
vector遍历
#include<bits/stdc++.h>
using namespace std;
vector<int> a[100100];
int n,m,i,j,x,y;
int main(){
cin >> n>> m;
for(i=1;i<=m;i++){
cin>> x>> y;
a[x-1].push_back(y);//这里使用a[x]也是可以的
}
for(i=0;i<n;i++){
cout << a[i].size();
sort(a[i].begin(),a[i].end());//对每一个向量排序
for(j=0;j<a[i].size();j++){
cout << " "<<a[i][j];
}
cout<< endl;
}
return 0;
}
vector排序
#include<bits/stdc++.h>
using namespace std;
vector<int> a[1005];//定义向量数组
int main(){
int n,c,x;
cin >> n;
for(int i=1;i<=n;i++){
cin >> c;
for(int j=1;j<=c;j++){
cin>> x;
a[i].push_back(x);
}
sort(a[i].begin(),a[i].end());
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
for(int j=0;j<a[i].size();j++){
cout << a[i][j]<< " ";
}
cout << endl;
}
}