zoukankan      html  css  js  c++  java
  • 重学树状数组6/14(P3368 【模板】树状数组 2)

    前几天考了个树状数组的题.....不会 别人都A了 十分丢人

    于是回来重学一遍 幸亏60min学会了(我好菜啊)


    首先树状数组是一种树形结构,与线段树不同的是它只能查前缀和,只支持单点修改。(以后可能还可以扩展吧)

    画出一棵树状数组来之后我们可以看到 对于每一个tr点 存的都是一个区间的和 这个区间范围被特殊的位运算规则存在了tr下标里

    单点修改的方式是

    void add(int x,int k) {//a[i] + k
        while (x<=n){
            tr[x] += k;
            x += lowbit(x);
        }
    }

    我们既然对一个点进行了修改,那么在tr数组中包含了这个点的tr也要进行修改

    修改的方式就是在原下标上不断地加他当前的lowbit作为新下标,然后对此tr做加法

    如果换成位运算的方式,就是在每一位1上加(这个说法太xie了 我不会说= =)(所以这个范围规则真的很鬼)

    求1~x前缀和的方式是

    int query(int x){// 1 ~x sum
        int ret = 0;
        while(x>0){
            ret += tr[x];
            x -= lowbit(x);
        }
        return ret;
    }

    这也是不断地在当前数上减去他的lowbit然后求和(感性理解(这个真能感性理解但给定义很难))

    对于普通数组来说,求范围和是O(n)的,而树状数组是O(logn)的

    单点修改普通数组O(1),树状数组O(logN)(其中N为数组总大小)

    区间修改普通数组加查分O(1)树状数组O(logN)(其中N为数组总大小)

    最后给出luogu树状数组2的代码

    #include<bits/stdc++.h>
    
    using namespace std ;
    
    const int MAXN = 500010;
    int tr[MAXN],n,m,a[MAXN],x,y,z;
    int lowbit(int x){return x & (-x);}
    void add(int x,int k) {//a[i] + k
        while (x<=n){
            tr[x] += k;
            x += lowbit(x);
        }
    }
    int query(int x){//1~x sum
        int ret = 0;
        while(x>0){
            ret += tr[x];
            x -= lowbit(x);
        }
        return ret;
    } 
    
    signed main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        int last=-1,now=-1;
        cin>>last;
        a[1] = last;
        for(int i=2;i<=n;i++){
            cin>>now;
            a[i] = now - last;
            last = now ;
        }
        for(int i=1;i<=n;i++){
            add(i,a[i]);
        }
    //    for(int i=1;i<=n;i++){
    //        cout<<"a["<<i<<"]="<<a[i]<<endl;
    //    }
        for(int i=1;i<=m;i++){
            int flag;
            cin>>flag;
            if(flag == 1){
                cin>>x>>y>>z;
                add(x,z);
                add(y+1,-z);
            }
            if(flag == 2){
                cin>>x;
                cout<<query(x)<<endl;
            }
        }
        return 0;
    }

    像这种基础数据结构就要常常回来复习,万一哪天考了呢

    TAG:SIN_XIII 

  • 相关阅读:
    Python_turtle绘图实例(持续更新)
    C++程序设计实验考试准备资料(2019级秋学期)
    利用next_permutation()实现全排列 完成 阮小二买彩票
    用埃氏算法来素数求和
    C++指针注意事项
    double与float的输入输出格式
    图片文件隐写术
    文件操作与隐写
    MFC 消息机制
    MFC应用中处理消息 创建窗口和会话框的顺序
  • 原文地址:https://www.cnblogs.com/SINXIII/p/11022715.html
Copyright © 2011-2022 走看看