最近剛剛深入到了樹狀陣列是什麼,上年寒假學過,但是當時完全聽不到,最近兩天沉下心來,好好看了下,終於懂這個原理是什麼,感覺並不是很難,而且很好用。
這個圖應該更好理解:
d[1]=a[1];
d[2]=a[1]+a[2];
d[3]=a[3];
d[4]=a[1]+a[2]+a[3]+a[4];
依次類推,6管著5和6 8管著前8項,如果乙個n (偶數)除以2還是乙個偶數那他將是這個n項的和,如果是奇數的那他將管著n-1和第n項這兩項的和
比如說對陣列a,改變某一位的值需o(1),求某個k區間值o(k);
這樣的m次操作是用o(m*k);
顯然資料很大時,效率要差很多;
而樹狀陣列,它改變某一位,或者求某個區間的和,都是o(logn);效率大為改善;
對於上圖怎麼計算區間的和;關鍵是需要幾個函式;
先說樹狀陣列最簡單的用法,修改上面圖中的某個點,並求某段區間的和;
下面介紹幾個函式,用這幾個來處理樹狀陣列的問題。
第乙個函式;
1這個函式主要是用來求的是某個點管轄範圍;int lowbit(intx)2
如果是x+=x&(-x);就是得到的改點的父節點的值;比如x=4時;就能得到8;
而x-=x&(-x)的話,就是得到x這個點的管轄區間的下個區間的管轄點;
比如說,x=7,x&(-x)等於1,此時x=6不斷迴圈到0能依次得到 6. 4.;
對於乙個偶數他整除2還是偶數那麼他將是前幾項的和 它進行x&(-x)等於他自己的本身,奇數為1,可以自己手動列印幾組觀察下。
把他們所有的管轄區間正好是1....7;
第二個函式
1這個函式,是用來修改樹狀陣列的;從當前點開始到它的爸爸,爺爺,這樣的長輩都得需要改變。void update(int x,int
num)
28 }
如果是一般的演算法只用修改改點就可;但是樹狀陣列必須修改所有改點被管轄的區間;
比如把a陣列的 a[2]減去1,(令n=16);則所有2被管轄的點有4,8,16都應該減去1;
就是呼叫函式 update(2,-1);
第三個函式
1這個函式就是求區間和了。。比如getsum(7)的話,就是求a[1]+a[2]+...a[7];int getsum(intx)2
9return
s;10 }
上面是最基本的用法;要學習樹狀陣列必須把上面的過程原理搞明白;
它這樣求和 比如7 會先加7 然後加6 然後加4 7包括自己 ,6包括5和6,4包括前四項,所以這樣就求出來了前七項的和。
題目大體上可以分為兩種(還有其他的就不多介紹了):
一,每次修改的是乙個點,所求的是關於某段區間;
二,每次修改的是乙個區間,所求的值是關於某個點的;
推薦部落格:
推薦題目:hdu 1556 color the ball hdu 2689 sort it hdu 1166 poj2352 stars
相關題解在樹狀陣列專欄有。
hdoj5792 樹狀陣列 未完待續
題意 求有多少種四個數滿足aa ab,ac ad,1 a b n 1 c d n 思路 只要找到兩種情況就成立了。在序列中對於乙個元素在他的後面存在比他大的,還有就是存在對於乙個元素在他的後面比他小的,那麼對於乙個元素的 種情況總和 種情況總和 但是這樣不難發現是有重複的。大哥說有四種可能。前面比他...
nginx 未完待續
yum install y pcre yum install y pcre devel yum install y openssl yum install y openssl devel yum install y zlib yum install y gccyum安裝 yum install y ...
sqlparse(未完待續)
sqlparse.split sql,encoding none sql 包含乙個或多個sql語句的字串 encoding 語句的編碼 可選 sql select from foo select from bar sql list sqlparse.split sql print sql list ...