树状数组模板

129 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路

树状数组基础模板

树状数组通常可以适用于单点修改单点查询区间修改和区间查询只不过在适用于后面的情况时需要进行一点修改

基础模板

template<class T>
struct BIT
{
    int lowbit(int x){ return x & -x;}
    int tree[N];
    int size;
    void resize(int x) {size = x;}
    void add(int x,T k)
    {
    for(x; x <= size; x += lowbit(x)) tree[x] += k;
    }
     int calc(int x)
    {
    T res = 0;
    for(x; x ; x -= lowbit(x)) res += tree[x];
    return res;
    }
};

基础模板适用于单点修改单点查询或者是单点修改前缀和查询 如果我们想将树状数组用于前缀和查询时需要我们使用差分来进行处理

区间查询模板


template<class T>
struct BIT
{
    int lowbit(int x){ return x & -x;}
    int size;
    void resize(int x) {size = x;}
    int tr[2][N];
    void add(int p, int x) {
    for(int i = p; i <= size; i += lowbit(i)) {
        tr[0][i] += x, tr[1][i] += x * p;
    }
    }
     void range_add(int l, int r, int x) {
         add(l, x), add(r + 1, -x);
     }
     int ask(int p) {
         int res = 0;
         for(int i = p; i; i -= lowbit(i)) {
             res += (p + 1) * tr[0][i] - tr[1][i];
    }
         return res;
     }
     int range_ask(int l, int r) {
         return ask(r) - ask(l - 1);
     }
};

树状数组二分模板

template<class T>
struct BIT
{
    int lowbit(int x){ return x & -x;}
    int tree[N];
    int size;
    void resize(int x) {size = x;}
    void add(int x,T k)
    {
    for(x; x <= size; x += lowbit(x)) tree[x] += k;
    }
     int calc(int x)
    {
    T res = 0;
    for(x; x ; x -= lowbit(x)) res += tree[x];
    return res;
    }
    int find(int s) {
   int pos = 0;
   for(int j = 18; j >= 0; j--)
      if(pos + (1 << j) <= n && tree[pos + (1 << j)] <= s) {
         pos |= 1 << j;
         s -= tree[pos];
      }
      return pos;
}
};

树状数组二分通常可以用来求最大ai\sum a_i<= s并且支持单点修改的操作

总结

虽然树状数组可以的操作线段树都可以实现但是树状数组的优点就是在代码量上比较小