牛客网小白月赛5I区间(差分数组)

链接:https://www.nowcoder.com/acm/contest/135/I
来源:牛客网

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

    Apojacsleam喜欢数组。

    他现在有一个n个元素的数组a,而他要对a[L]-a[R]进行M次操作:

        操作一:将a[L]-a[R]内的元素都加上P

        操作二:将a[L]-a[R]内的元素都减去P

    最后询问a[l]-a[r]内的元素之和?
    请认真看题干及输入描述。

输入描述:

输入共M+3行:

第一行两个数,n,M,意义如“题目描述”

第二行n个数,描述数组。

第3-M+2行,共M行,每行四个数,q,L,R,P,若q为1则表示执行操作2,否则为执行操作1

第4行,两个正整数l,r

输出描述:

一个正整数,为a[l]-a[r]内的元素之和
示例1

输入

复制
10 5
1 2 3 4 5 6 7 8 9 10
1 1 5 5
1 2 3 6
0 2 5 5 
0 2 5 8
1 4 9 6
2 7

输出

复制
23

说明

解题思路:这个题目用暴力应该很简单,但是很明显肯定会超时。看了别人的题解好像都是用前缀和加上差分数组或者线段树,觉得用差分数组前缀和简单点,首先设一个add数组用来存每个位置的变化值,先清0,假如是修改[l,r]区间,该区间每个数加p的话,add[l]+=p,add[r+1]-=p,当然m次操作完了之后,此时add[i]还不是a[i]的变化值,要求a[i]的变化值,需要求add数组的前缀和,求完之后add[i]即是代表了a[i]的变化值了,对add数组和a数组同时求区间和就是a[l]-a[r]内的元素之和。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1000005;
 5 int n,m,tl,tr,q,l,r,p;
 6 int a[maxn],add[maxn];
 7  
 8 int main()
 9 {
10     memset(add,0,sizeof(add));
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)
13         scanf("%d",a+i);
14     for(int i=1;i<=m;i++)
15     {
16         scanf("%d%d%d%d",&q,&l,&r,&p);
17         if(q==1)
18         {
19             add[l]-=p;
20             add[r+1]+=p;
21         }
22         else
23         {
24             add[l]+=p;
25             add[r+1]-=p;
26         }
27     }
28     scanf("%d%d",&tl,&tr);
29     ll sum=0;
30     for(int i=1;i<=n;i++)
31         add[i]+=add[i-1];
32     for(int i=tl;i<=tr;i++)
33         sum+=a[i]+add[i];
34     printf("%lld
",sum);
35     return 0;
36 }
原文地址:https://www.cnblogs.com/zjl192628928/p/9381501.html