总结:1037 - CSP 2021 提高级第一轮
一、 单项选择题
-
以比较为基本运算,对于 \(2n\) 个数,同时找到最大值和最小值,最坏情况下需要的最小的比较次数为( )。
\(\texttt A\). 4n-2
\(\texttt B\). 3n+1
\(\color{#5eb95e}\texttt{C}\). 3n-2
\(\color{#e74c3c}\texttt D\). 2n+1【解析】:
首先先将原数组两两分组。每组求一个最大,一个最小。使用 \(n\) 次。
这样化成 \(n\) 组最大和最小。此时直接最大与最大进行比较,最小与最小进行比较,使用 \(2n-2\) 次。
总共有 \(n+2n-2=3n-2\) 次。
【反思】:
思维不够。
-
G 是一个非连通简单无向图(没有自环和重边),共有 36 条边,则该图至少有( )个点。
\(\texttt A\). 8
\(\color{#e74c3c}\texttt B\). 9
\(\color{#5eb95e}\texttt C\). 10
\(\texttt D\). 11【反思】:
审题不认真:
G 是一个非连通简单无向图(没有自环和重边),共有 36 条边,则该图至少有( )个点。
-
前序遍历和中序遍历相同的二叉树为且仅为( )。
\(\texttt A\). 只有 1 个点的二叉树
\(\color{#e74c3c}\texttt B\). 根结点没有左子树的二叉树
\(\texttt C\). 非叶子结点只有左子树的二叉树
\(\color{#5eb95e}\texttt D\). 非叶子结点只有右子树的二叉树【反思】:
不要只考虑根的情况,在遍历中,所有部分都是根。
二、阅读程序
(一)
#include <iostream> #include <cmath> using namespace std; const double r = acos(0.5); int a1, b1, c1, d1; int a2, b2, c2, d2; inline int sq(const int x) { return x * x; } inline int cu(const int x) { return x * x * x; } int main() { cout.flags(ios::fixed); cout.precision(4); cin >> a1 >> b1 >> c1 >> d1; cin >> a2 >> b2 >> c2 >> d2; int t = sq(a1 - a2) + sq(b1 - b2) + sq(c1 - c2); if (t <= sq(d2 - d1)) cout << cu(min(d1, d2)) * r * 4; else if (t >= sq(d2 + d1)) cout << 0; else { double x = d1 - (sq(d1) - sq(d2) + t) / sqrt(t) / 2; double y = d2 - (sq(d2) - sq(d1) + t) / sqrt(t) / 2; cout << (x * x * (3 * d1 - x) + y * y * (3 * d2 - y)) * r; } cout << endl; return 0; }
分析程序
首先这个程序的第 \(5\) 行的地方,有一个 \(\arccos(0.5)\),这个有一点常识就知道 \(cos(60^{\circ})=0.5\),所以这个是 \(\arccos(0.5)=60^{\circ}=60\times\pi\div 180=\displaystyle \frac\pi3\)。
而球的体积公式为 \(\displaystyle\frac34 \pi r^3\)。
所以这个应该跟球的体积有关系。
后面 t = sq(a1 - a2) + sq(b1 - b2) + sq(c1 - c2)
可以推测出来是球心距,而 t <= sq(d2 - d1)
是判断两个球是否包含,t >= sq(d2 + d1)
是判断是否相交,所以推测这个是两个球的体积并。
这个可以参考这篇文章:球的体积并(计算几何+球缺)。
然后就没有然后了。
#include <algorithm> #include <iostream> using namespace std; int n, a[1005]; struct Node { int h, j, m, w; Node(const int _h, const int _j, const int _m, const int _w): h(_h), j(_j), m(_m), w(_w) { } Node operator+(const Node &o) const { return Node( max(h, w + o.h), max(max(j, o.j), m + o.h), max(m + o.w, o.m), w + o.w); } }; Node solve1(int h, int m) { if (h > m) return Node(-1, -1, -1, -1); if (h == m) return Node(max(a[h], 0), max(a[h], 0), max(a[h], 0), a[h]); int j = (h + m) >> 1; return solve1(h, j) + solve1(j + 1, m); } int solve2(int h, int m) { if (h > m) return -1; if (h == m) return max(a[h], 0); int j = (h + m) >> 1; int wh = 0, wm = 0; int wht = 0, wmt = 0; for (int i = j; i >= h; i--) { wht += a[i]; wh = max(wh, wht); } for (int i = j + 1; i <= m; i++) { wmt += a[i]; wm = max(wm, wmt); } return max(max(solve2(h, j), solve2(j + 1, m)), wh + wm); } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; cout << solve1(1, n).j << endl; cout << solve2(1, n) << endl; return 0; }
代码分析
这个稍微写了线段树的人就知道是一个最大字段和问题。现在来重点考一下我错了的题。
错题分析
25.solve1(1, n) 的时间复杂度为( )。
\(\texttt A\). \(\Theta(\log n)\)
\(\color{#5eb95e}\texttt B\). \(\Theta(n)\)
\(\color{#e74c3c}\texttt C\). \(\Theta(n \log n)\)
\(\texttt D\). \(\Theta(n^2)\)
这个可以分析一下:\(T(n)=2\cdot T(n/2)=n\)。
本文作者:辜铜星
本文链接:https://www.cnblogs.com/gutongxing/p/18415591
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步