zoukankan      html  css  js  c++  java
  • AcWing243一个简单的整数问题2(树状数组+差分+前缀和规律)

    题目地址https://www.acwing.com/problem/content/244/

    题目描述

    给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

    1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。

    2、“Q l r”,表示询问 数列中第 l~r 个数的和。

    对于每个询问,输出一个整数表示答案。

    输入格式

    第一行两个整数N,M。

    第二行N个整数A[i]。

    接下来M行表示M条指令,每条指令的格式如题目描述所示。

    输出格式

    对于每个询问,输出一个整数表示答案。

    每个答案占一行。

    数据范围

    1N,M1e5,
    |d|10000,
    |A[i]|1000000000

    题解:这是对树状数组的更深一步的扩展:区间加、区间求和。所以需要解决两个问题:区间加、区间和。区间加比较容易,直接差分就可以。至于区间和我们可以想办法求出原序列a的前缀和表示方法,b是原序列的差分数组

    这张图片中的蓝色的,每一行蓝色的和都是一个元素a,分别表示a[1].....a[x].所以我们只需要求出a的前缀和,那么对于区间的和就显而易见了。至于图中的红色是一个填补的作用,我们可以知道a的前缀和就是蓝色+红色再减去红色。首先,蓝色+红色=a[x]*(x+1),而a[x]可以由差分数组b的前缀和求出。红色其实是i*b[i]的前缀和。所以a的前x的和S[x]=b[i]的前缀和*(x+1)-i*b[i]的前缀和。所以查询[l,r]=S[r]-S[l-1]

    AC代码

    #include<iostream>
    #include<cstring> 
    using namespace std;
    const int N=1e5+10;
    #define lowbit(x) (x&(-x))
    #define ll long long int
    ll a[N]={0},b[N]={0},c[2][N]={0},n,m;
    
    void add(int k,int x,ll d){
        while(x<=n){
            c[k][x]+=d;
            x+=lowbit(x);
        }
    }
    
    ll sum(int k,int x){
        ll sum=0;
        while(x>0){
            sum+=c[k][x];
            x-=lowbit(x);
        }
        return sum;
    }
    
    ll prefix_sum(int x){
        return sum(0,x)*(x+1)-sum(1,x);
    }
    
    int main(){
        cin>>n>>m;
        memset(c,0,sizeof(c));
        ll now=0,x;
        for(int i=1;i<=n;i++){
            cin>>x;
            a[i]=x-now;
            now=x;
        }
        for(int i=1;i<=n;i++){
            add(0,i,a[i]);//差分数组a[i]
            add(1,i,i*a[i]);//差分数组i*a[i] 
        } 
        char ch;
        ll l,r,d;
        while(m--){
            cin>>ch;
            if(ch=='C'){
                cin>>l>>r>>d;
                add(0,l,d);
                add(0,r+1,-d);
                add(1,l,l*d);
                add(1,r+1,(r+1)*(-d));
            } 
            else {
                cin>>l>>r;
                cout<<(prefix_sum(r)-prefix_sum(l-1))<<endl;
            }
        }
        return 0;
    }

    写于:2020/8/26 17:27


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    【Git&GitHub idea中使用Git 03】
    【Git&GitHub 本地库和远程库交互 02】
    【Git&GitHub 本地库操作 01】
    C Primer Plus学习笔记【11章节】
    Python包,模块理解,以及通过元类自动化注册属性。
    pandas.DataFrame.from_dict的使用介绍
    C Primer Plus学习笔记 第10章 编程练习
    CMOS与BIOS的区别(转帖)
    Python 元类详解 __new__、__init__、__call__[补充说明]
    Python 元类详解 __new__、__init__、__call__[收官之作]
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/13566382.html
Copyright © 2011-2022 走看看