zoukankan      html  css  js  c++  java
  • 树状数组基本模板

    树状数组可以很方便地实现数组的动态修改求和,并且代码量非常小!经过拓展之后,还可以实现区间修改单点查询、求区间最值和第 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 }

  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4366714.html
Copyright © 2011-2022 走看看