PAT甲级 1104. Sum of Number Segments (20)

本文介绍了一个算法问题,即计算给定正数序列中所有连续子序列(片段)内数字的总和。通过分析规律,文章提供了一种高效计算的方法,并附带了C++实现代码。

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


题目大意

给你一组数据,让你求任意两个位置之间的数字和的和。

题目解析

这种题打个表,找规律就好,每个数字加上的次数都是有规律的。

#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
const int MAXN = 100000 + 5;
const int MAXM = 100000 + 5;
const int INF = 0x7f7f7f7f;
const int dir[][2] = {0,1,1,0,0,-1,-1,0};
template <class XSD> inline XSD f_min(XSD a, XSD b) { if (a > b) a = b; return a; }
template <class XSD> inline XSD f_max(XSD a, XSD b) { if (a < b) a = b; return a; }
bool cmp(int x, int y){return x>y;}
int n, m;

void Getdata(){
}
void Solve(){
    double a[MAXN], sum = 0.0;
    for(int i=0; i<n; i++) scanf("%lf", &a[i]);
    for(int i=0; i<n; i++) sum += a[i]*(n-i)*(i+1);
    printf("%.2f\n",sum);
}
int main(){
    while(~scanf("%d", &n)){
        Getdata();
        Solve();
    }
    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、付费专栏及课程。

余额充值