一、学习到的知识点
1、栈
概念:
栈是一种线性数据结构。栈只允许在一端(称为栈顶)进行插入和删除操作。栈中没有元素时,称为空栈。栈的插入操作通常被称为“压栈”(push),而删除操作则被称为“弹栈”(pop)。
语法:
stack<int> a;
a.push(e); //将e放入栈顶
a.pop(); //将栈顶元素出栈
a.top(); //获取栈顶元素
a.size(); //获取栈中有效元素个数
a.empty(); //检测栈是否为空
2、队列
概念:
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。
语法:
queue<int> a;
a.push(a); //将元素插入队列的末尾
a.front(); //返回队列的第一个元素
a.back(); //返回队列的最后一个元素
a.pop(); //从队列的开头删除元素
a.size(); //返回队列中元素的数量
a.empty(); //检查队列是否为空,如果为空则返回true,否则返回false
3、优先队列
概念:
既然是队列那么先要包含头文件#include <queue>。而他和queue不同的地方就在于我们可以自定义其中数据的优先级,让优先级高的排在队列前面优先出队。
优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。
语法:
priority_queue<int, vector<int>,greater<int> > q;
↑
从小到大排序,不写的话则为从大到小排序
4、函数stio( ) (自学)
在C++中,stoi()
函数是将字符串转换为整数的函数,其作用是将一个字符串类型的数字转换为一个整数类型的数字。
stoi()
函数的原型如下:
int stoi(const string& str, size_t* pos = 0, int base = 10);
其中,str是要转换的字符串,pos是一个指向size_t类型的指针,用于存储转换过程中第一个无法转换的字符的位置,base表示要转换的进制数,默认为10进制。
stoi()函数会从字符串的开头开始读取数字字符,直到遇到第一个非数字字符为止,然后将读取到的数字字符转换为整数类型的数字。如果字符串的开头不是数字字符,则返回0。
例如,stoi("123")的返回值为整数类型的123。
5、函数substr( ) (自学)
ubstr()
是C++标准库中的一个成员函数,可用于从一个字符串中提取子串。它的语法如下:
std::string substr (size_t pos, size_t len) const;
其中pos
是子字符串的起始位置(从0开始计数),len
是子字符串的长度。
以下是一个简单的例子,展示如何使用substr
函数取出字符串中间的几个字符:
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!";
// 取出从位置6开始的5个字符
std::string sub = str.substr(6, 5);
std::cout << sub << std::endl; // 输出: World
return 0;
}
在这个例子中,程序将输出字符串"Hello, World!"
中第6个字符开始的连续5个字符"World"
。如果len
超出了字符串的长度,它将返回从pos
到字符串末尾的一个子字符串。
6、集合set
概念:
set是一个集合,所有元素在插入时,会自动排序,并且不能插入重复元素。底层代码为红黑树。
set不允许容器中有重复的元素。
语法:
set<Type> a;
a.insert(val); //将值为val的元素插入set容器中
a.erase(val); //从set容器中删除值等于val的元素
a.size(); //返回set容器中元素的个数
a.empty(); //检查set容器是否为空,如果为空则返回true,否则返回false
a.clear(); //删除set容器中的所有元素
a.count(val); //返回set容器中值等于val的元素的个数(返回值只能是0或1,因为set中元素唯一)
进阶篇:(迭代器)
a.begin(); //返回set第一个元素的地址的迭代器
a.end(); //返回set最后一个元素的地址的下一个地址的迭代器
a.find(val); //返回一个迭代器,指向set容器中值等于val的元素,如果未找到则返回指向容器末
//尾的迭代器end()。
a.erase(start, end); //删除迭代器范围内的元素。
a.lower_bound(val); //返回一个迭代器,指向set容器中第一个不小于val的元素
a.upper_bound(val); //返回一个迭代器,指向set容器中第一个大于val的元素
a.equal_range(val); //返回一个pair,包含两个迭代器,分别指向set容器中等于val的元素的起始位置和
//结束位置
7、map
概念:
map简介
map是STL的一个关联容器,它提供一对一的hash。
- 第一个可以称为关键字(key),每个关键字只能在map中出现一次;
- 第二个可能称为该关键字的值(value);
map以模板(泛型)方式实现,可以存储任意类型的数据,包括使用者自定义的数据类型。Map主要用于资料一对一映射(one-to-one)的情況,map內部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能。在map内部所有的数据都是有序的。
map的功能
自动建立key - value的对应。key 和 value可以是任意你需要的类型,包括自定义类型。
语法:
C++ maps是一种关联式容器,包含 “关键字 / 值” 对
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数, (因为key值不会重复,所以只能是1 或 0)
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
遍历map的方法
for(auto [x,c] : mp){
}
8、关闭同步流
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
二、题解
T1、
题目:STL3 - stack, queue, deque, priority_queue C - 表达式求值
题解:
看到只有加号和乘号的时候,其实就会发现这一题不会很麻烦。而对于数字和符号,我们可以分别用以两个栈来存储它们。同时只要求输出答案的最后四位,所以我们可以在所有计算之后对10000取余。
困难与解决办法:
但是对于如何在一个字符串中,截取出数字放入栈中对我仍然是个难题。于是通过上网查询,我学到了函数stio()以及函数substr()。当然也可以以s[i] - '0'的形式逐个取出数字。
代码:
#include <iostream>
#include <stack>
using namespace std;
void jisuan(stack<int>& a, stack<char>& b) {
int x = a.top();
a.pop();
int y = a.top();
a.pop();
char s = b.top();
b.pop();
if(s == '+'){
a.push((x + y) % 10000);
}
else{
a.push(x * y % 10000);
}
}
int main()
{
string s;
cin >> s;
stack<int> a;
stack<char> b;
for(int i = 0;i < s.size();i++){
char x = s[i];
if (x >= '0' && x <= '9'){
int j = i;
while (j < s.size() && s[j] >= '0' && s[j] <= '9'){
j++;
}
int x = stoi(s.substr(i, j - i)) % 10000;
a.push(x);
i = j - 1;
}
else if(x == '*'){
while (b.size() && b.top() == '*'){
jisuan(a, b);
}
b.push(x);
} else if (x == '+'){
while (b.size()){
jisuan(a,b);
}
b.push(x);
}
}
while (b.size()){
jisuan(a,b);
}
cout << a.top();
return 0;
}
T2、
题目:练习题 D - Shifts and Sorting
题解:
首先明确,本题就是要让 0都往前去,1都往后去,因此不难想到将一个由前面 x − 1个 1 与后面 1 个 0 组成的字符串搞好的最小的代价。显然是该串长度——首先证明可行,整段做一遍,0 到最前面,代价为长度 x;再证明最优,其它的方式无论怎么倒腾都不可能避免让每一个点都被移动过一次,那样答案就不可能比总长度更小。
所以我们先做一个字符串是s[ ],读入1和0串,再从左往右遍历。读到1的时候,记下索引 i,继续遍历,如果遍历到最后一个字符还是1,则结束。反之当读到0时,我们记下索引 j 。移动最后的0到最前面,把1一次往后移,这样一次的行为成本就是 j - i + 1。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
string s;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t;
while(t--){
cin >> s;
int len = s.length();
s = " " + s;
int f = 0;
int ans = 0;
for(int i = 1;i <= len;i++) {
if (s[i] == '0' && f != 0) {
swap(s[f], s[i]);
ans += i - f + 1;
for(int j = f + 1;j <= i;j++) {
if (s[j] == '1') {
f = j;
break;
}
}
}
if (s[i] == '1' && f == 0) {
f = i;
}
}
cout << ans << "\n";
}
return 0;
}
T3、
题目:大一周六个人练习赛(2) A-B 数对
题解:
刚开始做的时候想着能无脑暴力枚举的,但是很快写完代码后就TLE了。于是我们想到要简化问题。求A - B = C 我们可以简化成A - C = B,只要找出有哪些数减去C之后等于B的,于是我们就想到了用map来做。
代码:
#include <bits/stdc++.h>
#include <map>
#include <string.h>
#define int long long
using namespace std;
const int N = 2e5 + 10;
int x[N];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,c,t = 0;
cin >> n >> c;
map<int,int> mp;
for(int i = 0;i < n;i++){
cin >> x[i];
mp[x[i]] += 1;
x[i] -= c;
}
for(int i = 0;i < n;i++){
t += mp[x[i]];
}
cout << t;
return 0;
}