目录
总结:
A-1
题意:
思路:
AC代码:
A-2
题意:
AC代码:
A-3
题意:
思路:
A-4 Big Number
题意:
思路:
AC代码
第一次打PAT甲级可能也是最后一次打了,可能因为今天蓝桥国赛,就我一个人考,考场上主要还是不太适应英文题面,老是看样例猜题意,第一个题一看是个地图乍以为是个搜索,读了20分钟题看懂题意是个模拟,交了一发13分,想不出来测试点,于是看第二题,看样例以为直接用队列就行了,沉下心看题目,结果要按题意双栈模拟队列,调试了20分钟AC了,第三题常规的建树,求每个节点的度,调试20分钟AC了,这时一看排名33。就接着看第四题,看样例和题意都没看懂,这时还有1个半小时结束,后面又排序骗了5分,最后又回去想第一题的测试点,测不出来。一个半小时坐牢,就这样结束了这次考试。
赛后又补了下题,找队友一起读题读懂了A4, 还没测,以下代码是都是凭记忆写的,等过两天可以测题了,会再更新。
给定一个N*N的地图,地图上有障碍物,规定从最后一行走,即最后一行列为1~n的为起点,可以一直往上走,遇到障碍物后往左走,若往左走能走出边界则也算能走出去,求不能走出地图的起点为多少。
模拟,枚举每个起点即可
待补~
给你两个栈,模拟一个队列,并且给出每次deque操作的时间。
#include
#define all(s) s.begin(), s.end()
using namespace std;
const int N = 1e5 + 7;
string op;
int n, x, k;
stack s1, s2;
int main() {
cin.tie(nullptr)->ios::sync_with_stdio(false);
cin >> n;
while (n -- ) {
cin >> op;
if (op == "I") {
cin >> x;
s1.push(x);
} else {
if (s1.empty() && s2.empty()) {
cout << "ERROR\n";
continue;
}
if (s2.empty()) {
while (!s1.empty()) {
s2.push(s1.top());
s1.pop();
k += 2;
}
}
cout << s2.top() << ' ' << ++ k << endl;
k = 0;
s2.pop();
}
}
return 0;
}
给你一颗二叉树的先序遍历和中序遍历,求每个顶点的度。
递归建树,再进行从根节点dfs计算每个节点的度,注意节点范围在int,因此最好开个map。
#include
using namespace std;
const int N = 1e3 + 7;
int n;
int inOrder[N], preOrder[N];
unordered_map mp, degree;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};
TreeNode *build(int inL, int inR, int preL, int preR) {
if (inL > inR) return nullptr;
int curRoot = preOrder[preL];
auto *root = new TreeNode(curRoot);
int k = mp[curRoot];
root->left = build(inL, k - 1, preL + 1, preL + k - inL);
root->right = build(k + 1, inR, preL + k - inL + 1, preR);
return root;
}
void DFS(TreeNode *root) {
if (!root) return ;
if (root->left) {
degree[root->val] ++;
DFS(root->left);
}
if (root->right) {
degree[root->val] ++;
DFS(root->right);
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> inOrder[i], mp[inOrder[i]] = i;
for (int i = 1; i <= n; i++) cin >> preOrder[i];
TreeNode *root = build(1, n, 1, n);
DFS(root);
int n0 = 0, n1 = 0, n2 = 0;
for (auto [k ,v] : mp) {
if (degree[v] == 0) n0 ++;
if (degree[v] == 1) n1 ++;
if (degree[v] == 2) n2 ++;
}
cout << n0 << " * " << n1 << " / " << n2 << " = " << (int)(n0 * 1.0 * n1 / n2);
return 0;
}
这题当时考场上读了1小时没读懂题目,赛后问队友才明白题意。
给你n张卡牌,卡牌的一面写着索引(1-n)一面写着一位数的数字,这意味着n的若卡牌的一面为大于等于10的数字,则这个卡牌的索引和数字是确定的,若两面都为小于10的数字,则两面都可以互用,要求你按照索引给出最后拼成的最小的数字。
索引为10~n的数字是确定的,那么我们只考虑索引为1~9的即可,对于每个索引为1~9的我们找出当前可以放置的数字最小的,然后再把用过的这个边删掉即可。时间复杂度大概O(10 * (n + e))
#include
#define all(s) s.begin(), s.end()
using namespace std;
const int N = 1e5 + 7;
int n, a, b;
vector g[N];
int main() {
cin.tie(nullptr)->ios::sync_with_stdio(false);
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a >> b;
if (a >= 10) swap(a, b); //索引是 y 数字是x
if (a < 10 && b < 10) {
g[a].push_back(b), g[b].push_back(a);
} else if (a < 10 && b >= 10) {
g[b].push_back(a);
}
}
for (int i = 1; i <= n; i++) {
if (i >= 10) cout << g[i][0];
else {
int minv = *min_element(all(g[i]));
g[minv].erase(find(all(g[minv]), i));
cout << minv;
}
}
return 0;
}