zoukankan      html  css  js  c++  java
  • 区间修改区间求和的树状数组

    好像树状数组虽然常数小,编程简单,可是资瓷的操作有限,

    普通的树状数组只资瓷单点修改和区间查询,首先要将其升级为区间修改

    我们利用差分来进行

    定义差分数组b[i]=a[i]-a[i-1]

    这样$ a[j]=sum_{i=1}^jb[i] $

    这样我们只要用树状数组维护一下b[i]的前缀和就好了

    修改区间[l,r]时我们只需要add(l,x)和add(r+1,-x)就好了

    题目链接

    就是一个树状数组资瓷区间修改和单点查询的模板

    但是这还不够

    我们还要区间求和

    我们来看

    $ sum_{i=1}^ja[i]=sum_{i=1}^jsum_{k=1}^ib[k] $

    我们将上面的式子可以写成

    $ sum_{i=1}^ja[i]=sum_{i=1}^jb[i]*(j-i+1) $

    但是上面的式子还是不好维护

    我们将其化简为

    $ sum_{i=1}^ja[i]=j*sum_{i=1}^jb[i]-sum_{i=1}^jb[i]*(i-1) $(自己推一下,验证一下)

    这样我们就可以利用两个树状数组完成区间修改,查询的操作

    用两颗树状数组A,B,A维护b[i],B维护b[i]*(i-1)

    我们可以很容易得到查询结果就是A(r)*r-B(r)-A(l-1)*(l-1)+B(l-1)

    关于修改操作

    我们按之前的讨论维护即可

    附上代码

    题目链接

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<algorithm>
    const int mn = 100005;
    int n,m;
    struct Binary_tree{
    long long tr[mn];
    void add(int i,long long x)
    {
        while(i<=n)
        {
            tr[i]+=x;
            i+=i&-i;
        }
    }
    long long qsum(int i)
    {
        long long ret=0;
        while(i>0)
        {
            ret+=tr[i];
            i-=i&-i;
        }
        return ret;
    }
    }A,B;
    long long a[mn];
    int main()
    {
        int opt,x,y,z;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
           scanf("%lld",&a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            A.add(i,a[i]-a[i-1]);
            B.add(i,(a[i]-a[i-1])*(i-1));
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&opt,&x,&y);
            if(opt==1)
            {
                scanf("%d",&z);
                A.add(x,z);
                A.add(y+1,-z);
                B.add(x,z*(x-1));
                B.add(y+1,-z*y);
            }
            else {
            printf("%lld
    ",(A.qsum(y)*y-(x-1)*A.qsum(x-1))-B.qsum(y)+B.qsum(x-1));
            }
        }
        return 0;
    }

     

  • 相关阅读:
    java中浮点数的比较(double, float)(转)
    SVN与TortoiseSVN实战:补丁详解(转)
    常见名词解析
    SSL连接建立过程分析(1)
    Flash-使用变形面板制作花朵
    使用ReactiveCocoa实现iOS平台响应式编程
    【LaTeX排版】LaTeX论文排版&lt;三&gt;
    angularjs入门学习【指令篇】
    理解class.forName()
    malloc()与calloc差别
  • 原文地址:https://www.cnblogs.com/logeadd/p/8997714.html
Copyright © 2011-2022 走看看