• 树状数组(区间修改,区间查询 )


    首先还是先利用区间修改 单点查询用过的差分思想(将区间的修改操作变成单点的修改),我们先搞一个c数组作为差分数组

      a数组是原数组,c数组是差分数组。

    简单可证:

    a[1] = c[1] ,  a[2] = c[2] + c[1],  a[3] = c[3] + c[2] + c[1],……;

    那么可以得到以下式子:

    a[1]+a[2]+...+a[i]

    =c[1] + ( c[1] + c[2] ) + ... + ( c[1] + c[2] + ... + c[i] )

    =i*c[1]+(i-1)*c[2]+...+c[i]

    =i *(c[1]+c[2]+...+c[i])-1*c[2]-...-(i-1)*c[i]

    于是,我们再搞一个数组d=(i-1)*c[i]

    那之前的式子就可以表示为

    a[1]+a[2]+…+a[i]=i*(c[1]+c[2]+...+c[i])-(d[1]+d[2]+...+d[i]);

    #include<iostream>
    #include<cstdio> 
    using namespace std;
    
    long long n,m;
    long long a[500009]; 
    long long c[500009],d[500009];
    long long lowbit(long long x)
    {
        return (x&(-x));
    }
    void change(long long *e,long long x,long long k)
    {
        for(int i=x;i<=n;i+=lowbit(i))
        {
            e[i]+=k;
        }
    }
    long long query(long long *e,long long x)
    {
        long long sum=0;
        for(int i=x;i>=1;i-=lowbit(i))
        {
            sum+=e[i];
        }
        return sum;
    }
    inline long long read()
    {
        long long x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
            change(c,i,a[i]-a[i-1]);
            change(d,i,(long long)(i-1)*(a[i]-a[i-1]));
        }
        for(int i=1;i<=m;i++)
        {
            long long p;
            cin>>p;
            if(p==1)//修改 
            {
                long long r,l,v;
                cin>>l>>r>>v;
                change(c,l,v);
                change(c,r+1,-v);
                change(d,l,(long long)(l-1)*v);
                change(d,r+1,(long long)-r*v);
            }
            if(p==2)//统计 
            {
                long long r,l;
                cin>>l>>r;
                long long t1=query(c,l-1)*(l-1)-query(d,l-1);
                long long t2=query(c,r)*r-query(d,r);
                printf("%lld
    ",t2-t1);
            }
        }
        return 0;
    }
    /*
    5 2
    1 7 6 5 8
    1 2 3 1//修改【2~3】+1 
    2 2 4//查询2~4 
    */
  • 相关阅读:
    sql 索引创建
    sql 触发器
    sql 中延迟执行
    sql 存储过程 分页
    BETWEEN and
    sql case when 速记
    Set无序怎么办?
    TCP为什么需要3次握手与4次挥手
    定时器
    JAVA 类加载器 第14节
  • 原文地址:https://www.cnblogs.com/1129-tangqiyuan/p/11221329.html
Copyright © 2020-2023  润新知