zoukankan      html  css  js  c++  java
  • 树状数组的基本用法

    树状数组的基本用法和奇技淫巧

    树状数组是一种修改查找复杂度都是logN的实用的数据结构,大家应该都会,下面放一张熟的不能再熟的图装装样子

    树状数组最基本的操作:单点修改,前缀查询原理都懂就不赘述了,贴个代码。

    void add(int pos,int x)
    {
        for(;pos<=N;pos+=lowbit(pos))
            c[pos]+=x;
    }
    int query(int pos)
    {
        int sum=0;
        for(;pos;pos-=lowbit(pos))
            sum+=c[pos];
        return sum;
    }    

    有一种进阶操作,区间修改,单点查询

    这就要用到差分——让一个位置的前缀和等于它的值。所以查单点就就是查前缀和。

    那如何修改区间呢, 举个例子   比如我们让 区间4 5 7加上3

    原数组         1 4 5 7 10   ->  1 7 8 10 10

    差分数组     1 3 1 2 3     ->  1  6 1  2  0

    显而易见,整个区间加上一个数, 区间内部元素的差是不变的。

    在差分数组中,只有这个区间两头的数字改变了 (挺好理解的吧)

    于是 ,  就可以通过单点修改区间的两端来进行区间修改了。

    代码的话 基本操作和上面是一样的,只是意义不同了 , 唯一不一样的是读入的时候存的是差分数组

    for(int i=1;i<=N;i++)
    {
        cin>>a[i];
        add(i,a[i]-a[i-1]);
    }

    现在你们可能有一个大胆的想法 : 怎么实现区间修改区间查询

    下面就是奇技淫巧时间。 (标题已上线)

    还是要用差分数组, 下面我们简单推个式子。

    所以我们就可以开两个数状数组, 一个里面放c[i],一个里面放 i×c[i],就能实现区间查询了

    除了每次修改改的是两个数组, 其他操作都一样

    下面是代码

    #include<bits/stdc++.h>
    #define ull unsigned long long 
    #define lowbit(a) (a&-a)
    #define MAXN 200005 
    using namespace std;
    int N,M,a[MAXN];
    ull c1[MAXN],c2[MAXN];
    void add(int pos,ull x)
    {
        for(int i=pos;i<=N;i+=lowbit(i))
            c1[i]+=x,c2[i]+=x*pos;
    } 
    ull sum(int pos)                    //[1,pos]区间和 
    {
        ull s=0;
        for(int i=pos;i;i-=lowbit(i))        
            s+=c1[i]*(pos+1)-c2[i];
        return s;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>N;
        for(int i=1;i<=N;i++)
        {
            cin>>a[i];
            add(i,a[i]-a[i-1]);
        }
        cin>>M;
        while(M--)
        {
            int P,X,Y;
            ull Z;
            cin>>P;
            if(P==1)
            {
                cin>>X>>Y>>Z; 
                add(Y+1,-Z);
                add(X,Z);
            }
            else if(P==2)
            {
                cin>>X>>Y;
                cout<<sum(Y)-sum(X-1)<<endl;
            }
        }
        return 0; 
    }

    可以到 http://codevs.cn/problem/1082/ 交一下练练手

    好了就说这么多了。

    其实, 我想去学线段树了。。。

  • 相关阅读:
    assembly打包。
    调用jar程序,读取与jar同级的配置文件。
    java.lang.UnsupportedClassVersionError
    jar包程序 读取properties文件
    Mysql-5.7.10启动失败 。
    spring HibernateValidator 验证 子类不起作用
    Eclipse 启动Tomcat后web项目的classes的子文件夹中没有calss文件
    java.lang.Exception: Socket bind failed: [730013] An attempt was made to acc
    log4
    jquery.validationEngine
  • 原文地址:https://www.cnblogs.com/Elfish/p/7544623.html
Copyright © 2011-2022 走看看