• 树状数组基本模板


    树状数组可以很方便地实现数组的动态修改求和,并且代码量非常小!经过拓展之后,还可以实现区间修改单点查询、求区间最值和第 K 大值(继续学习之后再更新)

    基本功能的实现主要有三个函数,lowbit 、 add 、 getsum;

    单点加值区间求和:

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=1e5+5;        //数组大小
     5 
     6 int c[maxn];
     7 
     8 void init(){
     9     memset(c,0,sizeof(c));
    10 }
    11 
    12 inline int lowbit(int x){return x&(-x);}
    13 //lowbit函数,决定下一个/上一个覆盖区间
    14 
    15 void add(int x,int a,int n){
    16     for(int i=x;i<=n;i+=lowbit(i))c[i]+=a;
    17 }
    18 //单点加数
    19 
    20 int sum(int x){
    21     int ans=0;
    22     for(int i=x;i>0;i-=lowbit(i))ans+=c[i];
    23     return ans;
    24 }
    25 //区间求和

      

    动态单点更新并区间求最值功能:

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=1e5+5;        //数组大小
     5 inline int lowbit(int x){return x&(-x);}
     6 inline int max(int a,int b){return a>b?a:b;}
     7 int a[maxn],ma[maxn];        //a为原数组,ma为最大值数组
     8 
     9 void init(int n){
    10     for(int i=1;i<=n;i++){
    11         ma[i]=a[i];
    12         for(int j=1;j<lowbit(i);j<<=1)
    13             ma[i]=max(ma[i],ma[i-j]);
    14     }
    15 }
    16 //init函数是构建最大值数组的函数,其中 n 是数组长度,a 是原数组,ma 是区间最大值数组,表示 [ i - lowbit [ i ]  ,i ]区间内的最大值,对于每一个 i ,用被其覆盖的各个区间的最大值更新它。
    17 
    18 void change(int ind,int v,int n){
    19     a[ind]=v;
    20     for(int i=ind;i<=n;i+=lowbit(i)){
    21         ma[i]=v;
    22         for(int j=1;j<lowbit(i);j<<=1)
    23             ma[i]=max(ma[i],ma[i-j]);
    24     }
    25 }
    26 //将第ind个数更新为v
    27 
    28 int query(int l,int r){
    29     int ans=a[r];
    30     while(1){
    31         ans=max(ans,a[r]);
    32         if(l==r)break;
    33         for(r-=1;r-l>=lowbit(r);r-=lowbit(r))
    34             ans=max(ans,ma[r]);
    35     }
    36     return ans;
    37 }
    38 //查询 [ l , r ] 区间内的最大值,通过不断考虑 r 覆盖的区间中的最大值,将 r 不断左移直到等于 l ,返回这中间的最大值,对于每一次遍历的 r ,若 r 覆盖的区间在查询区间内,就直接使用该区间的最大值,然后左移 r 值原先 r 覆盖的区间左,若 r 覆盖的区间比查询区间大,就直接考虑 r 的值,然后将 r 左移至 k - 1 ;这样循环直到 l == r 。

    树状数组还有区间加值单点查询的功能:

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=1e5+5;        //数组大小
     5 
     6 int c[maxn];
     7 
     8 inline int lowbit(int x){return x&(-x);}
     9 
    10 void change(int x,int v,int n){
    11     while(x<=n){
    12         c[x]+=v;
    13         x+=lowbit(x);
    14     }
    15 }
    16 
    17 int sum(int x){                        //求x单点值
    18     int s=0;
    19     while(x){
    20         s+=c[x];
    21         x-=lowbit(x);
    22     }
    23     return s;
    24 }
    25 
    26 void update(int l,int r,int v){        //将区间[l,r]加v
    27     change(l,v);
    28     change(r+1,-v);
    29 }

  • 相关阅读:
    菜鸟系列docker——docker镜像下(5)
    菜鸟系列docker——docker镜像中(4)
    菜鸟系列docker——docker镜像上(3)
    菜鸟系列docker——docker仓库(2)
    菜鸟系列docker——docker基本概念(1)
    Postman工具内容梳理
    Fiddler抓包手机APP失败的处理
    微信
    微信文本的爬取
    如何写活类的装饰器
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4366714.html
Copyright © 2020-2023  润新知