2021年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第2题)

2021年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第2题)

第2题
cpp 复制代码
01 #include <algorithm>
02 #include <iostream>
03 using namespace std;
04 
05 int n, a[1005];
06 
07 struct Node
08 {
09    int h, j, m, w;
10 
11    Node(const int _h, const int _j, const int _m, const int _w):
12   	 h(_h), j(_j), m(_m), w(_w)
13    {	}
14 
15    Node operator+(const Node &o) const
16    {
17    	return Node(
18    		max(h, w + o.h),
19    		max(max(j, o.j), m + o.h),
20   		 max(m + o.w, o.m),
21   		 w + o.w);
22    }
23 };  
24 
25 Node solve1(int h, int m)
26 {
27     if (h > m)
28     		return Node(-1, -1, -1, -1);
29     if (h == m)
30     		return Node(max(a[h], 0), max(a[h], 0), max(a[h], 0), a[h]);
31     int j = (h + m) >> 1;
32     		return solve1(h, j) + solve1(j + 1, m);
33 }
34 
35 int solve2(int h, int m)
36 {
37     if (h > m)
38     		return -1;
39     if (h == m)
40     		return max(a[h], 0);
41     int j = (h + m) >> 1;
42     int wh = 0, wm = 0;
43     int wht = 0, wmt = 0;
44     for (int i = j; i >= h; i--){
45     		wht += a[i];
46     		wh = max(wh, wht);
47     }		
48     for (int i = j + 1; i <= m; i++){
49     		wmt += a[i];
50     		wm = max(wm, wmt);
51     }
52     return max(max(solve2(h, j), solve2(j + 1, m)), wh + wm);
53 }
54 
55 int main()
56 {
57     cin >> n;
58     for (int i = 1; i <= n; i++) cin >> a[i];
59     cout << solve1(1, n).j << endl;
60     cout << solve2(1, n) << endl;
61     return 0;
62 }

假设输入的所有数的绝对值都不超过 1000 ,完成下面的判断题和单选题:

判断题
  1. 程序总是会正常执行并输出两行两个相等的数。( )

    A. 正确 B. 错误

  2. 第 28 行与第 38 行分别有可能执行两次及以上。( )

    A. 正确 B. 错误

  3. 当输入为 5 -10 11 -9 5 -7 时,输出的第二行为 7。( )

    A. 正确 B. 错误

单选题
  1. solve1(1, n) 的时间复杂度为( )。
    A. O(log⁡n)
    B. O(n)
    C. O(nlog⁡n)
    D. O( n 2 n^2 n2)
  2. solve2(1, n) 的时间复杂度为( )。
    A. O(log⁡n)
    B. O(n)
    C. O(nlog⁡n)
    D. O( n 2 n^2 n2)
  3. 当输入为 10 -3 2 10 0 -8 9 -4 -5 9 4 时,输出的第一行为( )。
    A. 13
    B. 17
    C. 24
    D. 12

题目代码分析

程序包含两个分治函数 solve1solve2,均用于求解允许空子段的最大子段和(即当所有元素为负时结果为 0)。

  • solve1 采用经典的分治合并法,结构体 Node 存储区间的四个关键信息:前缀最大和(h)区间最大子段和(j)后缀最大和(m)区间总和(w) 。合并操作 operator+ 可在 O(1) 内完成。
  • solve2 同样分治,但合并时通过两个循环分别求左半部分的最大后缀和右半部分的最大前缀和,合并代价与区间长度成正比。

判断题答案及解析
  1. 程序总是会正常执行并输出两行两个相等的数。

    • 当 (n \ge 1) 时,两函数均递归计算最大子段和,结果相等且非负。
    • 当 (n = 0) 时,solve1(1,0) 执行第 28 行返回 Node(-1,-1,-1,-1).j = -1solve2(1,0) 执行第 38 行返回 -1。输出均为 -1,仍相等。
    • 程序无崩溃风险,递归深度仅 (\log n),数组范围安全。故总是输出两个相等的数
      答案:A
  2. 第 28 行与第 38 行分别有可能执行两次及以上。

    • 递归过程中,划分区间 j = (h+m)>>1 保证左右子区间均非空(当 h < m 时,j ≥ hj < m)。因此内部递归不会出现 h > m 的情况。
    • 仅当初始调用 h > m(如 n = 0)时,各执行一次 。不可能执行两次或以上。
      答案:B
  3. 当输入为 5 -10 11 -9 5 -7 时,输出的第二行为 7

    • 数组:-10, 11, -9, 5, -7
    • 最大子段和显然是单独元素 11(或 11 -9 +5 = 7 更小),故结果应为 11
    • 第二行是 solve2 的输出,应为 11,而非 7
      答案:B

单选题答案及解析
  1. solve1(1, n) 的时间复杂度

    • 递归式 (T(n) = 2T(n/2) + O(1)),合并操作为常数时间。由主定理,时间复杂度为 O(n)
      答案:B
  2. solve2(1, n) 的时间复杂度

    • 递归式 (T(n) = 2T(n/2) + O(n))(两个循环各扫描半个区间),由主定理,时间复杂度为 O(n log n)
      答案:C
  3. 当输入为 10 -3 2 10 0 -8 9 -4 -5 9 4 时,输出的第一行

    • 数组:-3, 2, 10, 0, -8, 9, -4, -5, 9, 4
    • 枚举连续子段,最大和为 2 + 10 + 0 -8 + 9 -4 -5 + 9 + 4 = 17(下标 2~10)。
    • solve1(1,n).j 即此最大子段和,结果为 17
      答案:B

专栏推荐:信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新)
https://blog.csdn.net/weixin_66461496/category_13125089.html


各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

1、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html

2、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

CSP信奥赛C++一等奖通关刷题题单及题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新)
https://blog.csdn.net/weixin_66461496/category_13125089.html

3、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html

4、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
樱木Plus2 天前
深拷贝(Deep Copy)和浅拷贝(Shallow Copy)
c++
blasit4 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_5 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星5 天前
虚函数表:C++ 多态背后的那个男人
c++
端平入洛7 天前
delete又未完全delete
c++
端平入洛8 天前
auto有时不auto
c++
哇哈哈20219 天前
信号量和信号
linux·c++
多恩Stone9 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
蜡笔小马9 天前
21.Boost.Geometry disjoint、distance、envelope、equals、expand和for_each算法接口详解
c++·算法·boost
超级大福宝9 天前
N皇后问题:经典回溯算法的一些分析
数据结构·c++·算法·leetcode