樹狀陣列總結

2021-09-25 04:03:27 字數 1570 閱讀 3920

因為樹狀陣列用得比較少,所以今天總結一下常見用法。(順便貼一些板)

首先上樹狀陣列的定義:設原陣列為a,樹狀陣列為c,那麼c[i]=a[i-2^k+1]+a[i-2^k+2]……+a[i]。其中k為i的二進位制狀態下最後面連續的0的個數。

然後我們就可以得出樹狀陣列的修改和查詢操作了。

下面貼一下查詢和修改的板:

int find(int x)

return s;

}

int change(int x,int y)

}

樹狀陣列的基本操作就在上面了,下面講一下一些常見的問題。

1、單點修改+區間查詢

這個上面已經講過了

2、區間修改+單點查詢

這乙個我們要用到差分思想:設b[i]=a[i]-b[i-1],而c維護的是b的和而不是a的和,那麼區間修改x~y的時候我們就只需要修改x和y+1即可。

**如下:

#include#include#include#define maxn 500010

int a[maxn],c[maxn],n,m,x,y,k,type;

int find(int x)

return s;

}int change(int x,int y)

}int main()

else

m--;

}}

3、區間修改+區間查詢

這乙個我們還是要用到差分思想,有上面的問題我們的到a[x]=b[1]+b[2]...+b[x],那麼我們就有

a[1]+a[2]+a[3]...+a[x]

=b[1]+(b[1]+b[2])+(b[1]+b[2]+b[3])+...+(b[1]+b[2]...+b[x])

=b[1]*x+b[2]*(x-1)+b[3]*(x-2)+...+b[x]*1

=x*(b[1]+b[2]+...+b[x])-(b[1]*0+b[2]*1+b[3]*2+...+b[x]*(x-1))

到這裡就十分清晰了。我們只需用兩個樹狀陣列,分別維護b[i]的和以及b[i]*(i-1)就可以了。

下面貼一下**:

#include#include#include#define ll long long

#define maxn 100010

ll a[maxn],c1[maxn],c2[maxn],n,m,x,y,k;

char type;

ll find1(ll x)

return s;

}ll find2(ll x)

return s;

}int change1(ll x,ll y)

return 0;

}int change2(ll x,ll y)

return 0;

}ll sum(ll x)

int main()

else

m--;

}return 0;

}

樹狀陣列的常數很小,**很短,但是處理的範圍窄。在做一些有關求和問題的時候不妨用一用。

樹狀陣列總結

樹狀陣列的基本知識已經被各種大牛和菜鳥講到爛了,我就不多說了,下面給出基本操作的 假定原陣列為a 1.n 樹狀陣列b 1.n 考慮靈活性的需要,使用int a傳陣列。define lowbit x x x int sum int a,int x void update int a,int x,int...

樹狀陣列總結

樹狀陣列是對乙個陣列改變某個元素和求和比較實用的資料結構。兩中操作都是o logn 在解題過程中,我們有時需要維護乙個陣列的字首和s i a 1 a 2 a i 但是不難發現,如果我們修改了任意乙個a i s i s i 1 s n 都會發生變化。可以說,每次修改a i 後,調整字首和s在最壞情況下...

樹狀陣列總結

今天學習了一下樹狀陣列,做乙個簡單總結。樹狀陣列可分為兩種操作,1 修改單個點,統計區間和 一般為 向上修改 update1 向下統計 sum1 2 修改區間,統計單個點 一般為向下修改 update2 向上統計 sum2 主要模板如下 int c n int lowbit int x 用於確定區間...