数据结构--树状数组

逻辑琉璃探
• 阅读 889

Feature


To deal with dynamic continuous and query problem, and for a given array: $A_1, A_2, \dotsc A_n$, we're asked to support these two operations:

  • let $A_x$ increase $d$
  • calculate $A_L+A_{L+ 1}+\dotsc +A_R$

To make our algorithm cost less time, we introduce (Binary Indexed Tree, BIT). Before we introduce the concept of the BIT, we need to discuss lowbit

Lowbit


It's the number that is represented by the rightmost "1".

Property


If $i$ is left child, then it's father's index is $i+lowbit(i)$, and right child is correspond to $i-lowbit(i)$.

If we set the nodes by set the same lowbit of their index at the same height layer, we can gain a beautiful binary tree.

数据结构--树状数组

数据结构--树状数组

Calculate Lowbit With Bit-operation


$lowbit(x)= x\& -x$

Important Auxiliary Array


$C_i= A_{i-lowbit(i)+1}+A_{i-lowbit(i)}+\dotsc +A_i$

Take picture lowbit tree 2 for example$C_i$ represents the sum of the red line which contains the index $i$. For example, $C_{12}$ is the sum of the red line, and this red line contain $A_9, A_{10}, A_{11}, A_{12}$.

Use $C_i$ Calculate The Sum Of Prefix


"Climb the tree". Here are the rules.

  • Begin from the end of the prefix sum.
  • Find the higher node which has smaller index.
  • Find the nearest node which satisfy the second rules.
  • Sum the $C_i$ up along the way you climb.

Update $C_i$ If Some $A_j$ Changes


"Climb the tree". Here are the rules.

  • Begin from the changed point.
  • Find the higher node which has bigger index.
  • Stop at the highest node of the current BIT.
  • Change the $C_i$ you met along the way you climb.

Code


int C[MAX_N+1], n;       //n represent the length of A
int Sum(int i)
{
    int s= 0;
    while (i> 0){
        s+= C[i];
        i-= i& -i;
    }
    return s;
}
void Add(int i, int x)
{
    while(i<= n){
        C[i]+= x;
        i+= i&-i;
    }
}

2-D BIT


The second dimension is a bit whose nodes' element is also a BIT.

OJ Practise


POJ 1656

My first code, it's still use the idea of 1-D BIT and it doesn't have a high efficiency.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

const int wd= 101;

int bo[wd][wd];
int C[wd][wd];

inline int Lowbit(int x){
    return x & (-x);
}
int Sum(int x, int y)   //(x, y)
{
    int s= 0;
    while (y>0){
        s+= C[x][y];
        y-= Lowbit(y);
    }

    return s;
}
void Add(int x, int y, int d)
{
    while (y< wd){
        C[x][y]+= d;
        y+= Lowbit(y);
    }
}
void BUpdate(int x, int y, int L)
{
    for (int i= x; i<x+L; ++i){
        for (int j= y; j<y+L; ++j){
            if (!bo[i][j]){
                bo[i][j]= 1;
                Add(i, j, 1);
            }
        }
    }
}
void WUpdate(int x, int y, int L)
{
    for (int i= x; i<x+L; ++i){
        for (int j= y; j<y+L; ++j){
            if (bo[i][j]){
                bo[i][j]= 0;
                Add(i, j, -1);
            }
        }
    }
}
int Answer(int x, int y, int L)
{
    int s= 0;

    for (int i= x; i<x+L; ++i){
        s+= (Sum(i, y+L-1)- Sum(i, y-1));
    }
    printf("%d\n", s);

    return s;

}

int main()
{
    int t, x, y, L;
    char cd[7];
    scanf("%d", &t);
    memset(bo, 0, wd*wd*sizeof(int));
    memset(C, 0, wd*wd*sizeof(int));

    while (t--){
        scanf("%s %d %d %d", cd, &x, &y, &L);

        switch(cd[0]){
            case 'W':
                WUpdate(x, y, L);
                break;
            case 'B':
                BUpdate(x, y, L);
                break;
            case 'T':
                Answer(x, y, L);
                break;
            default:
                break;
        }
    }
    return 0;
}

This has $O( \log (N) \times \log (W))$ time. $N\& W$ is the length and the width of the rectangle.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

const int wd= 101;

int bo[wd][wd];
int C[wd][wd];

inline int Lowbit(int x){
    return x & (-x);
}
int Sum(int x, int y)   //(x, y)
{
    int s= 0, tpy;
    while (x>0){
        tpy= y;
        while (tpy>0){
            s+= C[x][tpy];
            tpy-= Lowbit(tpy);
        }
        x-= Lowbit(x);
    }

    return s;
}
void Add(int x, int y, int d)
{
    int tpy;
    while (x<wd){
        tpy= y;
        while (tpy< wd){
            C[x][tpy]+= d;
            tpy+= Lowbit(tpy);
        }
        x+= Lowbit(x);
    }
}
void BUpdate(int x, int y, int L)
{
    for (int i= x; i<x+L; ++i){
        for (int j= y; j<y+L; ++j){
            if (!bo[i][j]){
                bo[i][j]= 1;
                Add(i, j, 1);
            }
        }
    }
}
void WUpdate(int x, int y, int L)
{
    for (int i= x; i<x+L; ++i){
        for (int j= y; j<y+L; ++j){
            if (bo[i][j]){
                bo[i][j]= 0;
                Add(i, j, -1);
            }
        }
    }
}
int Answer(int x, int y, int L)
{
    int s= 0;

    s= Sum(x+L-1, y+L-1)+Sum(x-1, y-1)-Sum(x+L-1, y-1)-Sum(x-1, y+L-1);
    printf("%d\n", s);

    return s;

}

int main()
{
    int t, x, y, L;
    char cd[7];
    scanf("%d", &t);
    memset(bo, 0, wd*wd*sizeof(int));
    memset(C, 0, wd*wd*sizeof(int));

    while (t--){
        scanf("%s %d %d %d", cd, &x, &y, &L);

        switch(cd[0]){
            case 'W':
                WUpdate(x, y, L);
                break;
            case 'B':
                BUpdate(x, y, L);
                break;
            case 'T':
                Answer(x, y, L);
                break;
            default:
                break;
        }
    }
    return 0;
}
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Wesley13 Wesley13
3年前
HTTP面试题(二):HTTP请求报文和响应报文格式
!(https://oscimg.oschina.net/oscnet/0406894fb1274bee91fc53c84c516576.jpg)看都看了还不点个赞!(https://oscimg.oschina.net/oscnet/095d444dc9a449ee85afd19b00fdf52b.png)!(h
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
Duang,HUAWEI DevEco IDE全面升级啦
想感受全新UI带来的视觉及交互体验、HiKey970开发板调测、HiAIAPI推荐和收藏、深度AI模型分析等新功能,体验高清晰度和流畅度的远程AI真机调测吗?!(https://oscimg.oschina.net/oscnet/f4e1bb24ff00b8c6ea27f75370a53bfbacd.jpg)全新的UI设计
Wesley13 Wesley13
3年前
ES6 新增的数组的方法
给定一个数组letlist\//wu:武力zhi:智力{id:1,name:'张飞',wu:97,zhi:10},{id:2,name:'诸葛亮',wu:55,zhi:99},{id:3,name:'赵云',wu:97,zhi:66},{id:4,na
深入理解树状数组 | 京东物流技术团队
树状数组树状数组(BIT,BinaryIndexedTree)是简洁优美的数据结构,它能在很少的代码量下支持单点修改和区间查询,我们先以a可以发现:不是所有节点都是连接在一起的,c\作者:京东物流王奕龙来源:京东云开发者社区自猿其说Tech转载请注明来源
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
逻辑琉璃探
逻辑琉璃探
Lv1
雨后的彩虹,苏醒的野花显得格外清新。
文章
4
粉丝
0
获赞
0