https://github.com/xukeawsl/pat-solutions-cpp
The PAT (Advanced Level) Practice Solutions
https://github.com/xukeawsl/pat-solutions-cpp
cpp solutions
Last synced: about 1 month ago
JSON representation
The PAT (Advanced Level) Practice Solutions
- Host: GitHub
- URL: https://github.com/xukeawsl/pat-solutions-cpp
- Owner: xukeawsl
- Created: 2024-04-15T13:18:28.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-06-01T05:24:35.000Z (about 2 years ago)
- Last Synced: 2025-03-04T02:41:24.487Z (over 1 year ago)
- Topics: cpp, solutions
- Homepage: https://pintia.cn
- Size: 102 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# PAT 甲级题解
记录 PAT 甲级题目的 C++ 解答及其注意点, 并分享一些 C++ 刷题常用语法
试题链接:
1. [PAT官方](https://pintia.cn/problem-sets/994805342720868352/exam/problems/type/7)
2. [AcWing](https://www.acwing.com/problem/search/1/?csrfmiddlewaretoken=BZzs1DHQHamtbsPlyW88aT2Bt7nCuCta08kfejLs7EMgLEx7UozjHDTjCOiw3u82&show_algorithm_tags=0&search_content=PAT)
# C++ 刷题常用语法
## 离散化(数组去重)
```cpp
#include
#include
using namespace std;
vector arr = {1, 3, 2, 2, 4, 5};
sort(arr.begin(), arr.end()); // O(nlogn)
auto last = unique(arr.begin(), arr.end()); // 将相邻元素去重, last 为去重后的尾迭代器
arr.erase(last, arr.end()); // 删除 [last, arr.end()) 这部分重复出现的元素
// 以上步骤可以简化为如下, 时间复杂度是 O(n) 的
// arr.erase(unique(arr.begin(), arr.end()), arr.end());
```
## 数组求和
```cpp
#include
#include
using namespace std;
vector arr = {1, 3, 2, 2, 4, 5};
int sum = accumulate(arr.begin(), arr.end(), 0);
```
## 求数组最值
```cpp
#include
#include
using namespace std;
vector arr = {1, 3, 2, 2, 4, 5};
int maxval = *max_element(arr.begin(), arr.end()); // 返回最大值元素对应的迭代器
int minval = *min_element(arr.begin(), arr.end()); // 返回最小值元素对应的迭代器
// 返回最小值和最大值对应的迭代器(pair)
auto [minit, maxit] = minmax_element(arr.begin(), arr.end());
```
## 构建前缀和数组
```cpp
#include
#include
using namespace std;
vector arr = {1, 3, 2, 2, 4, 5};
vector presum(arr.size() + 1); // 需要分配足够的空间
partial_sum(arr.begin(), arr.end(), presum.begin() + 1);
```
## 读取输入行(包括空格)
```cpp
#include
#include
using namespace std;
string input;
getline(cin, input); // 如果之前有非字符串类型读取, 需要用 getchar() 读走回车符
```
## 根据空格分隔多个字符串
```cpp
#include
#include
#include
#include
using namespace std;
string input = "hello world c++";
istringstream in(input);
vector words;
string word;
while (in >> word) {
words.emplace_back(word);
}
```
## 优先级队列自定义比较规则
```cpp
#include
#include
#include
using namespace std;
priority_queue pq_max; // 默认是最大堆
priority_queue, greater> pq_min; // 最小堆
using PII = pair;
// 自定义比较规则, first 大的在上, first 相同时, second 小的在上
// priority_queue 的比较函数含义同 sort 相反, p1.first < p2.first 表示
// first 更大的在上, 而 sort 中表示 first 更小的在前
auto cmp = [](const PII& p1, const PII& p2) {
if (p1.first == p2.first) {
return p1.second > p2.second;
}
return p1.first < p2.first;
};
priority_queue, decltype(cmp)> pq_self{cmp};
pq_self.emplace(2, 1);
pq_self.emplace(2, 3);
pq_self.emplace(1, 3);
while (!pq_self.empty()) {
auto [a, b] = pq_self.top(); pq_self.pop();
cout << a << '-' << b << endl;
}
```
## 数组翻转
```cpp
#include
#include
using namespace std;
vector arr = {1, 3, 2, 2, 4, 5};
reverse(arr.begin(), arr.end());
```
## 求下一个排列
```cpp
#include
#include
using namespace std;
string s = "123";
// 下一个更大的排列是 132
// 如果不存在下一个更大的排列则返回 false, 且 s 转换为最小的排列
bool exist = next_permutation(s.begin(), s.end());
```
## 初始化一个下标数组
```cpp
#include
#include
using namespace std;
vector index(5);
// 从 0 开始填充, {0, 1, 2, 3, 4}
iota(index.begin(), index.end(), 0);
```
## 字符串数字互转
```cpp
#include
using namespace std;
string s = "666";
int digit = stoi(s); // 字符串转数字
//long digit = stol(s);
//long long digit = stoll(s);
s = to_string(digit + 1); // 数字转字符串
```
## 十进制转二进制字符串
```cpp
#include
#include
#include
using namespace std;
bitset<32> b(-234); // 指定 32 位整数
cout << b.to_string() << endl; // 对于负数, 得到的是补码的字符串表示
cout << b.count() << endl; // 得到二进制表示下 1 的个数
```
## 最大公约数/最小公倍数
```cpp
#include
using namespace std;
int a = 3, b = 6;
int g = __gcd(a, b); // algorithm 提供了 __gcd 但是没有提供 lcm
// 自己实现 lcm
int lcm(int a, int b) {
return a * b / __gcd(a, b);
}
// c++17 标准 numeric 提供了 gcd 和 lcm 函数
// 不过它们适用于 common_type,对于 __int128_t 这种类型不适用
// 可以使用上面的 __gcd 来实现
#inlucde
int a = 3, b = 4;
int g = gcd(a, b);
int l = lcm(a, b);
```
## 红黑树容器使用
### 迭代器
```cpp
// 注意点 1, 关于指向末尾的迭代器
// set 和 map 的尾迭代器 end 存放了容器中的元素个数
// 因此解引用 end 迭代器是没问题的, 对 end 执行自减操作
// 可以得到容器尾部的元素
auto it = prev(st.end());
// 注意点 2,关于指向起始的迭代器
// set 和 map 的起始迭代器当容器为空时和 end 相同
// 对 begin 执行自减操作还是得到的 begin 而不是 end
// 因此需要注意不要造成死循环了
```
### 自定义比较规则
```cpp
// 以 pair 为例, 假设规定以 first 从大到小排列, first 相同时
// 以 second 从小到大排列
using PII = pair;
auto cmp = [](const PII& p1, const PII& p2) {
if (p1.first == p2.first) {
return p1.second < p2.second;
}
return p2.first < p1.first;
};
set st(cmp);
```