• 树状数组


    树状数组是一种可以在O(log n)内区间求和或单点修改的数据结构,因其代码简单且不需递归,效率较线段树高。

    树状数组的实现:

    1. Lowbit:lowbit(k)是指整数k的二进制的右数第一个1以右的部分的大小,如(6)10=(110)2则lowbit(6)=(10)2=(2)10

      lowbit的简单实现:一个数加一个负号是把这个数的二进制取反+1,如-10的二进制就是-1010=0101+1=0110,则lowbit(10)=0110&1010=0010。即

      1 #define lowbit(x) (x&(-x))
    2. 定义:数组a为储存原始数据的数组,数组c为树状数组。
    3. 实现树状数组:(并未完全理解,先记忆,回头复习)

      初始化令c[k]=a[k]+a[k-1]+…+a[lowbit(k)];

      1     for(i=1;i<=n;i++){
      2         cin>>a[i];
      3         a[i]+=a[i-1];//读入时用前缀和初始化
      4     };
      5     for(i=1;i<=n;i++)
      6         c[i]=a[i]-a[i-lowbit(i)];//初始化令c[k]=a[k]+a[k-1]+…+a[lowbit(k)];

      则区间求和可以写为:

      1 int get(int k){
      2     int sum=0;
      3     while(k>0){
      4         sum+=c[k];//加上a[k]至a[lowbit(k)]的值
      5         k-=lowbit(k);//将指针前移lowbit(k)个位置
      6     }
      7     return sum;
      8 }

      同样的,单点修改可以写为:

      1 void add(int k,int x){
      2     while(k<=n){
      3         c[k]+=x;//将a[k]的值增加x,并更新c数组
      4         k+=lowbit(k);//将指针前移lowbit(k)个位置
      5     }
      6 }
    4. 例题:codevs 1080(线段树练习)
      #include<iostream>
      #include<cstring>
      #include<algorithm>
      #define lowbit(x) (x&(-x))
      using namespace std;
      
      int a[200000],c[200000];
      int i,j,n;
      
      int get(int k){
          int sum=0;
          while(k>0){
              sum+=c[k];//加上a[k]至a[lowbit(k)]的值
              k-=lowbit(k);//将指针前移lowbit(k)个位置
          }
          return sum;
      }
      
      void add(int k,int x){
          while(k<=n){
              c[k]+=x;//将a[k]的值增加x,并更新c数组
              k+=lowbit(k);//将指针前移lowbit(k)个位置
          }
      }
      
      int main(){
          int k,m;
          memset(a,0,sizeof(a));
          memset(c,0,sizeof(c));
          cin>>n;
          for(i=1;i<=n;i++){
              cin>>a[i];
              a[i]+=a[i-1];//读入时用前缀和初始化
          };
          for(i=1;i<=n;i++)
              c[i]=a[i]-a[i-lowbit(i)];//初始化令c[k]=a[k]+a[k-1]+…+a[lowbit(k)];
          cin>>m;
          for(i=1;i<=m;i++){
              cin>>k;
              if(k==1){cin>>k>>j;add(k,j);}
              else{cin>>k>>j;cout<<get(j)-get(k-1)<<endl;}
          }
      }
  • 相关阅读:
    Introduce myself
    二叉搜索树的后序遍历序列(剑指offer-23)
    从上到下打印二叉树(剑指offer-22)
    二叉树的深度(剑指offer-38)
    不用加减乘除做加法(剑指offer-48)
    栈的压入、弹出序列(剑指offer-21)
    Java容器
    包含min函数的栈(剑指offer-20)
    在Docker中创建Mongodb数据库
    词向量聚类实验
  • 原文地址:https://www.cnblogs.com/y-m-y/p/5716481.html
Copyright © 2020-2023  润新知