【深进1.例1】求区间和

题目理解

这道题要求我们处理多个区间求和查询。给定一个长度为n的整数序列,然后有m个查询,每个查询给出一个区间[l, r],要求计算该区间内所有数的和。

解题思路

暴力解法的问题

最直观的方法是对于每个查询,都从l到r遍历数组求和。这种方法的时间复杂度是O(mn),当n和m都达到10^5时,这样的时间复杂度会导致超时(10^10次操作在大多数OJ上都会超时)。

前缀和优化

前缀和是一种预处理技术,可以让我们在O(1)时间内回答任何区间和查询。具体思路是:

  1. 预处理阶段:创建一个前缀和数组s,其中s[i]表示数组前i个元素的和(a[1]到a[i])。

  2. 查询阶段:对于查询[l, r],区间和可以通过s[r] - s[l-1]计算得到。

这样,预处理时间复杂度是O(n),每个查询处理时间是O(1),总时间复杂度优化为O(n + m),完全可以处理题目给出的数据规模。

参考代码

#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;

int a[N], s[N], n, m; // 定义数组a存储原始数据,数组s存储前缀和

int main() {
    // 读取序列长度n
    cin >> n;
    
    // 读取序列并计算前缀和
    for (int i = 1; i <= n; i++) {
        cin >> a[i]; // 读取第i个元素
        s[i] = s[i - 1] + a[i]; // 计算前i个元素的和,存入s[i]
    }
    
    // 读取查询数量m
    cin>>m;
    
    // 处理每个查询
    while(m--){
        int L,R;
        cin>>L>>R; // 读取查询区间[L,R]
        // 输出区间和:前R项和减去前L-1项和
        cout<<s[R]-s[L-1]<<endl; 
    }

    return 0;
}

代码细节说明

  1. 数组定义:使用全局数组a和s,大小设为N=100005,满足题目数据范围要求。

  2. 前缀和计算:s[i] = s[i-1] + a[i]这个递推式是关键,它利用已计算的前缀和来快速计算新的前缀和。

  3. 查询处理:对于每个查询,直接使用前缀和数组做减法得到结果,避免了重复计算。

  4. 索引处理:注意s[L-1]的使用,因为区间包含第L个元素。

复杂度分析

  • 时间复杂度

    • 预处理阶段:O(n)(填充前缀和数组)

    • 查询阶段:O(m)(每个查询O(1))

    • 总时间复杂度:O(n + m)

  • 空间复杂度:O(n)(存储前缀和数组)

posted @ 2025-05-08 16:49  行胜于言Ibl  阅读(148)  评论(0)    收藏  举报