1. 程式人生 > 其它 >考研C語言資料結構-圖(圖的鄰接矩陣實現 + 廣度、深度優先遍歷)

考研C語言資料結構-圖(圖的鄰接矩陣實現 + 廣度、深度優先遍歷)

樹狀陣列學習筆記

簡介

樹狀陣列是一個可以在 \(O(\log n)\) 的時間複雜度內支援單點修改和查詢字首和的操作的資料結構。

\(\text{lowbit}\)

\(\text{lowbit}\) 是指一個數在二進位制下最末尾的1的位置。\(\text{lowbit(x) = x and -x}\)

寫法

建立

把編號為 \(i\) 的點和編號為\(i+\text{lowbit}(i)\)的點連起來。

然後把點\(i\)到根節點路徑上的所有點的\(val\)加上\(a_i\)

修改

把點\(i\)到根節點路徑上的所有點的\(val\)加上\(data\)

查詢

如果要查詢\([l,r]\)

的和,就可以用\(r\)的字首和減去\(l-1\)的字首和。

如何求字首和呢?

就是從點 \(i\) 一直往下跳 (\(\text{-lowbit(i)}\)),直到跳到0,把中間的所有\(val\)加起來就是字首和了。

程式碼

int val[MAXN];
void change(int x,int data){//修改&建立
    for(int i=x;i<=MAXN;i+=lowbit(i))val[i]+=data;
}
int ask(int x){//字首和
    int ans=0;
    for(int i=x;i!=0;i-=lowbit(i))ans+=val[i];
    return ans;
}
int ask(int l,int r){//查詢
    return ask(r)-ask(l-1);
}

二維樹狀陣列

可以求出二維數組裡的字首和,時間複雜度\(O(\log^2 n)\)

與一維樹狀陣列相似。

int val[MAXN][MAXN];
void change(int x,int y,int data){//修改&建立
    for(int i=x;i<=MAXN;i+=lowbit(i))
    for(int j=y;j<=MAXN;j+=lowbit(j))
    val[i][j]+=data;
}
int ask(int x,int y){//字首和
    int ans=0;
    for(int i=x;i!=0;i-=lowbit(i))
    for(int j=y;j!=0;j-=lowbit(j))    
    ans+=val[i][j];
    return ans;
}
int ask(int x1,int y1,int x2,int y2){//查詢
    return ask(x2,y2)-ask(x2,y1-1)-ask(x1-1,y2)+ask(x1-1,y1-1);
}