(前缀和)51NOD 1081 子段求和

给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和。

例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} -1。3 + 7 + 9 = 19,输出19。

Input

第1行:一个数N,N为数组的长度(2 <= N <= 50000)。
第2 至 N + 1行:数组的N个元素。(-10^9 <= N[i] <= 10^9)
第N + 2行:1个数Q,Q为查询的数量。
第N + 3 至 N + Q + 2行:每行2个数,i,l(1 <= i <= N,i + l <= N)

Output

共Q行,对应Q次查询的计算结果。

Input示例

5
1
3
7
9
-1
4
1 2
2 2
3 2
1 5

Output示例

4
10
16
19

解

前缀和算法:

#include <stdio.h>
#include <malloc.h>
int main()
{
    int n;
    while (scanf_s("%d", &n) != EOF)
    {
        int *p = (int *)alloca(n * sizeof(int)),q;
        long long *pt = (long long *)alloca((n + 1) * sizeof(long long));
        for (int i = 0; i < n; i++)
        {
            scanf_s("%d", p + i);
            pt[i + 1] = pt[i] + p[i];
        }
        scanf_s("%d", &q);
        while (q--)
        {
            int i, l;
            scanf_s("%d%d", &i, &l);
            printf("%lld\n", pt[i+l-1] - pt[i-1]);
        }
    }
}

总结一些关于内存分配的知识点。

常见内存分为三大区域

1.静态存储区(全局变量,static类型的局部变量等)

内存区域大,2个G左右,2^28个字节。

2.栈(局部变量等)

内存区域小,1~2M,2^20个字节。处理速度快。

3.堆(动态内存分配)

内存区域大,2个G左右,2^28个字节。

动态内存分配的相关函数:

void *malloc(unsigned int num_bytes);(分配的内存是位于堆中的,并且没有初始化内存的内容。)

void *calloc(unsigned n,unsigned size);(分配的内存是位于堆中的,并且初始化内存的内容。)

void *realloc(void *mem_address, unsigned int newsize);(先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。)

void *alloca(_In_ size_t _Size) (分配的内存是位于栈中的,并且初始化内存的内容,作用域结束时会自动释放内存。)

void free(void* p);(释放动态分配的内存。未被释放的空间再次被无法使用。)

原文地址:https://www.cnblogs.com/Ekalos-blog/p/9683914.html

时间: 2024-10-14 14:30:53

(前缀和)51NOD 1081 子段求和的相关文章

51nod 1081 子段求和

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和. 例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} -1.3 + 7 + 9 = 19,输出19. Input 第1行:一个数N,N为数组的长度(2 <= N <= 50000). 第2 至 N + 1行:数组的N个元素.(-10^9 <= N[i] <= 10^9) 第N + 2行:1

1081 子段求和(前缀和)

1081 子段求和(前缀和)(51NOD基础题) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和. 例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} -1.3 + 7 + 9 = 19,输出19. Input 第1行:一个数N,N为数组的长度(2 <= N <= 50000). 第2 至 N + 1行:数组的N个元素.(-10^9 <= N

1081 子段求和

1081 子段求和 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和. 例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} -1.3 + 7 + 9 = 19,输出19. Input 第1行:一个数N,N为数组的长度(2 <= N <= 50000). 第2 至 N + 1行:数组的N个元素.(-10^9 <= N[i] <

51Nod 1081前缀和

#include <iostream> #include <stdio.h> using namespace std; long long a[50005]; long long sum[50005]; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; sum[i]=sum[i-1]+a[i]; } int q; cin>>q; while(q--) { int x

51nod 最大子段和

N个整数组成的序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a[j]的连续子段和的最大值.当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13.和为20. 简单DP  伪代码 start = 1answerstart = asnwerend = 1endmax = answer = a[1]   for end = 2 to n do        if endmax > 0 then        e

算法分析之最大子段求和

给定由n个整数(包含负整数)组成的序列a1,a2,...,an,求该序列子段和的最大值.当所有整数均为负值时定义其最大子段和为0.所求的最优值为: 例如,当(a1,a2, ……a7,a8)=(1,-3, 7,8,-4,12, -10,6)时,最大子段和为: 分治方法求解从问题的解的结构可以看出,它适合于用分治策略求解:如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情形:a[1:n]的最大子段和与a

51nod 1258 序列求和 V4

跪烂(貌似我记得,是我要学习多项式的一些东西,然后发现可以搞伯努利数,然后就奇怪的入坑了) 这个题显然是不可以n^2来预处理伯努利数的 那怎么办呢........找题解啊... 这里有伯努利数的生成函数,(不知道怎么推的),然后搞一搞就成了一个多项式求逆的样子. 而且这个题还有一个BT的就是,1e9+7是不能写成1+2^k*n的形式的,所以就没有办法直接NTT,这里还要用到一个三模数NTT,就是取出3个满足1+2^k*n形式的大质数(先假设为a,b,c吧),满足a*b*c>n*P*P(P在这里就

51nod 1228 序列求和

伯努利数,刚! 自然数幂和神犇的blog:  http://blog.csdn.net/acdreamers/article/details/38929067 伯努利数的2个重要的式子: 为什么图片这么大... 这样的话n^2预处理出伯努利数,然后就可做了 1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 const int M=2005; 6 const int maxn=2050; 7

51NOD 1712 - 区间求和

按题解思路,统计单点贡献 对于每个位置 x,把2x-l-r拆分成前后两部分,前部分NUM和后部分SUM可以在遍历时O(1)更新 #include <stdio.h> using namespace std; const int N = 1000005; typedef unsigned int ui; ui n, a[N]; ui suml[N], numl[N], numr[N], sumr[N], sum2[N], num2[N]; int main() { scanf("%u&