【PAT】【Advanced Level】1104. Sum of Number Segments (20)

本文介绍了一种针对正数序列求所有连续子序列(段)之和的算法,并提供了具体的实现代码。通过分析每个元素在不同子序列中出现的次数规律,实现了高效的求和计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1104. Sum of Number Segments (20)

时间限制
200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CAO, Peng

Given a sequence of positive numbers, a segment is defined to be a consecutive subsequence. For example, given the sequence {0.1, 0.2, 0.3, 0.4}, we have 10 segments: (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4).

Now given a sequence, you are supposed to find the sum of all the numbers in all the segments. For the previous example, the sum of all the 10 segments is 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N, the size of the sequence which is no more than 105. The next line contains N positive numbers in the sequence, each no more than 1.0, separated by a space.

Output Specification:

For each test case, print in one line the sum of all the numbers in all the segments, accurate up to 2 decimal places.

Sample Input:
4
0.1 0.2 0.3 0.4 
Sample Output:
5.00

原题链接:

https://www.patest.cn/contests/pat-a-practise/1104

思路:

找规律

对于一个长度为n的序列

第1个元素,累加了n*1次;

第2个元素,累加了(n-1)*2次;

。。。

第n个元素,累加了1*n次。

按此规律,边读入边计算即可

CODE:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
	int n;
	double res=0;
	scanf("%d",&n);
	for (int i=0;i<n;i++)
	{
		double t;
		scanf("%lf",&t);
		res+=(t*(double)(n-i)*(double)(i+1));
	}
	printf("%.2f",res);
	return 0;
}



### 关于分段求和的算法 对于分段求和问题,通常涉及的是如何高效计算特定区间内的数值总和。这类问题可以通过多种方法解决,具体取决于数据结构的选择以及查询模式。 #### 方法一:前缀和数组 一种简单而有效的方式是构建一个前缀和数组 `prefix_sums` 来存储到当前位置为止所有元素之和: ```python def build_prefix_sum(nums): prefix_sums = [0] * (len(nums) + 1) for i in range(1, len(prefix_sums)): prefix_sums[i] = prefix_sums[i - 1] + nums[i - 1] return prefix_sums ``` 通过这种方式,在后续处理区间的求和请求时只需做一次减法操作即可得到结果: ```python def query_segment_sum(l, r, prefix_sums): return prefix_sums[r + 1] - prefix_sums[l] ``` 这种方法的时间复杂度为 O(n),其中 n 是输入列表长度;每次查询的时间复杂度为 O(1)[^1]。 #### 方法二:线段树(Segment Tree) 当面对频繁更新的情况时,可以考虑使用更高级的数据结构——线段树来优化性能。线段树允许快速执行范围查询和单点修改操作,并保持较低的日志级别时间复杂度。 创建一棵覆盖整个数组范围 `[start,end]` 的线段树节点并初始化其值为零: ```python class SegmentTreeNode: def __init__(self, start, end, sum=0): self.start = start self.end = end self.sum = sum self.left = None self.right = None def build_tree(start, end, array): if start > end: return None root = SegmentTreeNode(start, end) if start == end: root.sum = array[start] return root mid = (start + end)//2 root.left = build_tree(start, mid, array) root.right = build_tree(mid+1, end, array) root.sum = root.left.sum + root.right.sum return root ``` 在线段树上实现区间求和功能如下所示: ```python def get_range_sum(node, q_start, q_end): if node is None or q_end < node.start or q_start > node.end: return 0 if q_start <= node.start and q_end >= node.end: return node.sum return get_range_sum(node.left, q_start, q_end) \ + get_range_sum(node.right, q_start, q_end) ``` 此方案适合动态变化场景下的高效查询需求,支持 O(logn) 时间内完成任意子区间求和的任务[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值