• 牛客小白月赛5-I-区间(差分求前缀和+一次暴力统计)


    题目描述

      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

    说明

    解题思路:显然这道题要操作的是区间修改,区间查询,但题目中有个坑就是给的内存太少了,用线段树懒标记模板或者是树状数组区间修改+区间查询模板都会超内存,仔细一看这题有一个突破口就是只有一次查询(划重点,如果是多次查询,则应该套公式,否则会超时),并且给定n的最大值只有106,因此我们可以利用树状数组差分求前缀和(实际并没用到树状数组,只是用了一个差分数组来模拟)+一次暴力统计区间[l,r]中所有元素的值即可。关于怎么利用差分来修改区间值和求前缀和,请看这篇:题解报告:Luogu P3368 【模板】树状数组 2(区间修改,单点查询)
    AC代码(673ms):
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn=1e6+5;
     5 int n,q,p,l,r,k,a[maxn];
     6 int main(){
     7     while(~scanf("%d%d",&n,&q)){
     8         memset(a,0,sizeof(a));
     9         for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    10         for(int i=n;i>=2;--i)a[i]-=a[i-1];//利用原数组从后往前差分
    11         while(q--){
    12             scanf("%d%d%d%d",&p,&l,&r,&k);
    13             if(p==1)k=-k;
    14             a[l]+=k,a[r+1]-=k;//区间修改操作
    15         }
    16         for(int i=2;i<=n;++i)a[i]+=a[i-1];//求前缀和,还原a[i]值
    17         scanf("%d%d",&l,&r);
    18         LL ans=0;
    19         for(int i=l;i<=r;++i)ans+=a[i];//O(n)统计区间[l,r]所有元素a[i]的值
    20         printf("%lld
    ",ans);
    21     }
    22     return 0;
    23 }
  • 相关阅读:
    JOI2017FinalC JOIOI 王国
    JOISC2017C 手持ち花火
    P4336 [SHOI2016]黑暗前的幻想乡
    SP104 HIGH
    P3160 [CQOI2012]局部极小值
    P4965 薇尔莉特的打字机
    【BZOJ4361】isn
    P3506 [POI2010]MOT-Monotonicity 2
    P3214 [HNOI2011]卡农
    P3704 [SDOI2017]数字表格
  • 原文地址:https://www.cnblogs.com/acgoto/p/9470316.html
Copyright © 2020-2023  润新知