Loading

二维树状数组

模板题:LOJ133
就是区间上的问题搬到了矩阵上。
但其实矩阵上的问题处理起来并不容易。比如这道题,涉及矩阵最大值,必须采用二维线段树(线段树套线段树)的方式进行维护,非常繁琐。
但对于LOJ133这道题,因为只有单点修改区间求和,所以考虑使用二维树状数组,即树状数组套树状数组。而二维树状数组写起来就要简单多了。

比如说,我们要维护一个 \(4\times4\) 的矩阵。我们可以考虑对行建立一个树状数组,再对每一行建立一个树状数组(如下图)。

方便起见,我们称外层树状数组(维护行)的结点为外层结点,内层树状数组(维护每一行)的结点为内层结点。

接下来就要支持两个操作了。实在是不好描述,直接放图了。

修改操作:比如我们修改了 \((1,2)\) 这个位置的值,树状数组上要修改的位置如图:

实现:
树状数组没有线段树那样的繁琐结构,直接开二维数组就完事了。

void add(int x,int y,int k)
{
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=m;j+=lowbit(j))
            a[i][j]+=k;
}

查询同理。显然矩阵查询可以化归为对以 \((1,1)\) 为左上顶点的矩阵的查询。比如我们查询 \((3,3)\)

code:

int query(int x,int y)
{
    int ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
        for(int j=y;j>=1;j-=lowbit(j))
            ans+=a[i][j];
    return ans;
}
//query(aa,bb;cc,dd)=query(cc,dd)-query(aa-1,dd)-query(cc,bb-1)+query(aa-1,bb-1)

嗯就这么简单。

posted @ 2022-02-09 12:02  pjykk  阅读(69)  评论(0编辑  收藏  举报