树状数组学习笔记

树状数组的基本操作这里就不再赘述(反正是笔记,我自己也记得)

单点修改,区间查询:

例题:树状数组1

int lowbit(int x){return (x&-x);}
struct bit{
    int c[N];
    void add(int x,int v){for(;x<=n;x+=lowbit(x))c[x]+=v;}
    int query(int x){
      int res=0;
      for(;x;x-=lowbit(x))res+=c[x];
      return res;
   }
};

区间修改,单点查询:

例题:树状数组2

这个实现十分的简单,我们只需要一颗树状数组维护一个差分序列就可以了。

struct bit2{
    int c[N];
    void add(int l,int r,int v){
        r++;
        for(;l<=n;l+=lowbit(l))c[l]+=v;
        for(;r<=n;r+=lowbit(r))c[r]-=v;
    }
    int query(int x){
        int res=0;
        for(;x;x-=lowbit(x))res+=c[x];
        return res;
    }
};

下面是的才是我想记录的:

区间修改,区间查询:

考虑和区间修改,单点查询一样,维护一个差分序列。

令原序列为 aa , 差分序列为 bb 。

我们的区间查询 \sum_{i=1}^n a_ii=1nai

根据差分的定义,我们区间查询转化为了 \sum_{i=1}^r \sum_{j=1}^i b_ji=1rj=1ibj

拆开柿子推导一下:

\sum_{i=1}^r \sum_{j=1}^i b_ji=1rj=1ibj

= b_1+2b_2+3b_3+4b_4……=b1+2b2+3b3+4b4

= \sum_{i=1}^r b_i\times (r-i+1)=i=1rbi×(ri+1)

= \sum_{i=1}^r b_i\times (r+1)-\sum_{i=1}^r b_i\times i=i=1rbi×(r+1)i=1rbi×i

于是我们开两个树状数组维护 b_ibi 和 b_i\times ibi×i

例题:线段树1

struct bit3{
    int b[N],c[N];
    void add(int l,int r,int v){
        r++;int vl=l*v,vr=r*v;
        for(;l<=n;l+=lowbit(l)){
            b[l]+=v;
            c[l]+=vl;   
        }
        for(;r<=n;r+=lowbit(r)){
            b[r]-=v;
            c[r]-=vr;
        }
    }
    int query(int x){
        int a1=0,a2=0,j=x,i=x;
        for(;i;i-=lowbit(i))a1+=b[i];
        for(;j;j-=lowbit(j))a2+=c[j];
        return a1*(x+1)-a2;
    }
};

你以为这就结束了?不!

这才刚刚开始。

二维树状数组,单点修改,平面区间查询

例题:二维树状数组1

struct bit4{
    int c[M][M];
    void add(int x,int y,int v){
        for(;x<=n;x+=lowbit(x)){
            int i=y;
            while(i<=n)c[x][i]+=v,i+=lowbit(i); 
        }           
    }
    int query(int x,int y){
        int res=0;
        for(;x;x-=lowbit(x))for(int i=y;i;i-=lowbit(i))res+=c[x][i];
        return res;
    }
};

二维树状数组,平面区间修改,单点查询

和一维树状数组一样,二维前缀和的操作代码里有,其他的都一样。

例题:二维树状数组2

struct bit5{
    int c[M][M];
    void ad(int x,int y,int v){
        for(;x<=n;x+=lowbit(x)){
            int i=y;
            while(i<=n)c[x][i]+=v,i+=lowbit(i); 
        }           
    }
    void add(int x,int y,int v){
        ad(x,y,v);ad(x+1,y,-v);ad(x,y+1,-v);ad(x+1,y+1,v);
    }
    int query(int x,int y){
        int res=0;
        for(;x;x-=lowbit(x))for(int i=y;i;i-=lowbit(i))res+=c[x][i];
        return res;
    }
};

最后,我们来看大BOSS

你准备好了吗?

二维树状数组,平面区间修改,平面区间查询

和一维基本思路是一致的,我们先推推柿子

\sum_{i=1}^x \sum_{j=1}^y a_{i,j}i=1xj=1yai,j

=\sum_{i=1}^x \sum_{j=1}^y \sum_{k=1}^i \sum_{t=1}^j b_{k,t}=i=1xj=1yk=1it=1jbk,t

(将柿子展开,跳一步。)

=(x+1)(y+1)\sum_{i=1}^x \sum_{j=1}^y b_{i,j}- (x+1)\sum_{i=1}^x \sum_{j=1}^y b_{i,j}\times j- (y+1)\sum_{i=1}^x \sum_{j=1}^y b_{i,j}\times i+ \sum_{i=1}^x \sum_{j=1}^y b_{i,j}\times ij=(x+1)(y+1)i=1xj=1ybi,j(x+1)i=1xj=1ybi,j×j(y+1)i=1xj=1ybi,j×i+i=1xj=1ybi,j×ij

或者把柿子换行方便查看:

=(x+1)(y+1)\sum_{i=1}^x \sum_{j=1}^y b_{i,j}=(x+1)(y+1)i=1xj=1ybi,j

- (x+1)\sum_{i=1}^x \sum_{j=1}^y b_{i,j}\times j(x+1)i=1xj=1ybi,j×j

- (y+1)\sum_{i=1}^x \sum_{j=1}^y b_{i,j}\times i(y+1)i=1xj=1ybi,j×i

+ \sum_{i=1}^x \sum_{j=1}^y b_{i,j}\times ij+i=1xj=1ybi,j×ij

现在我们可以码出来了

例题:上帝造题的七分钟

struct bit6{
    int a[M][M],b[M][M],c[M][M],d[M][M];
    void ad(int x,int y,int v){
        int vx=v*(x-1),vy=v*(y-1),vij=v*(x-1)*(y-1);
        for(;x<=n;x+=lowbit(x)){
            int i=y;
            while(i<=m){
                a[x][i]+=v;
                b[x][i]+=vy;
                c[x][i]+=vx;
                d[x][i]+=vij;
                i+=lowbit(i);   
            }
        }           
    }
    void add(int a,int b,int c,int d,int v){
        ad(a,b,v);ad(c+1,b,-v);ad(a,d+1,-v);ad(c+1,d+1,v);
    }
    int qu(int x,int y){
        int a1=0,a2=0,a3=0,a4=0;
        for(int i=x;i;i-=lowbit(i)){
            for(int j=y;j;j-=lowbit(j)){
                a1+=a[i][j];
                a2+=b[i][j];
                a3+=c[i][j];
                a4+=d[i][j];
            }
        }
        return a1*x*y-a2*x-a3*y+a4;
    }
    int query(int a,int b,int c,int d){
        return qu(c,d)-qu(c,b-1)-qu(a-1,d)+qu(a-1,b-1);
    };
}
 
posted @ 2022-08-25 11:46  灵长同志  阅读(198)  评论(3)    收藏  举报