• 树状数组


    树状数组是一种可以在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;}
          }
      }
  • 相关阅读:
    docker gitlab意外强制关机导致gitlab启动后报错unexpected end of JSON input
    Dockerfile实践记录
    html 打开新页面
    【rt-thread】2、尝试用ENV添加18b20传感器
    【rt-thread】1、快速建立rt-thread nano最小裁剪工程
    Git pull 强制覆盖本地文件
    *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    51单片机局部变量占用ram的问题
    【乐为物联】1、初识乐联
    Wing-AEP平台LWM2M设备接入
  • 原文地址:https://www.cnblogs.com/y-m-y/p/5716481.html
Copyright © 2020-2023  润新知