模板篇 樹狀陣列們(四)

2021-07-27 22:05:50 字數 2061 閱讀 5120

這是第四篇樹狀陣列了。。

我們之前講過樹狀陣列的以下幾大作用:

單點加區間查 不會的話->

區間加單點查 不會的話->

區間加區間查 不會的話->

然而上面的會不會的無所謂啊。。。

因為上面我們查的都是區間和性質的東西。。(就是用字首和差分能減出來的東西_ (:з」∠) _)

而我們今天要做的,是:

單點修改,區間查詢最大值

在這裡,我要給大家講一下時間複雜度,不過你們要答應我我說完不要走

我們拿能幹查詢最大值的兩樣其他東西來比,線段樹和rmq..

用樹狀陣列實現這個功能時,(又要畫醜陋的**)

種類線段樹

樹狀陣列

rmq初始化

nlogn

< nlogn

nlogn

查詢logn

logn1修改

單點&區間logn

單點< logn*logn

無法修改

上手難度

稍複雜較簡單

簡單常數

大(沒說你 zkw)小小

碼長稍長短不長

話說這麼一比,樹狀陣列究竟優勢在哪呢

然後因為lowbit的緣故時間複雜度會玄學很多。。看臉和資料了。。歐洲人民發來賀電

無所謂了。。(⊙v⊙)嗯就是這樣。。

我說過(嗎?)之前講的功能都可以不會。。

但我們還是要有一些知識儲備的……比如……樹狀陣列優美的、精巧的劃分區間的方式。。

各位大拿還記得小角落裡的lowbit麼~

樹狀陣列中第i個點所記錄的,是[i-lowbit(i)+1,i]的這lowbit(i)個數的資訊。我們既然要查詢的是最大值,自然這個陣列中維護的就是我們最可愛的最大值咯~~

說人話:樹狀陣列上的c[i]表示a[i-lowbit(i)+1]..a[i]範圍內的最大值..

然後查詢起來的**似乎就像這樣:

int ask(int l,int r)

return ans;

}

也可以看出來,其實真正的迴圈次數很少的……(logn也就是個上界,松的很……)

修改起來看上去慢一點,按照這種優美的劃分區間的方式,修改我們要這麼寫(注意是把點x改為s)

void update(int x,int s)

}

這裡看來,上界確實要到logn*logn的樣子?

但是,內層迴圈只需要迴圈到lowbit(i)..

(也就是說當n是奇數的時候是o(1)的(逃~))

然後,就到了我們的建樹。。(蛤?建樹不是加點就行了麼..)

喂~這裡的修改挺慢的啊~

我們有< nlogn的建樹方式呢,為什麼不用呢= =

建樹的**:

void init()

}

這樣的話功能就講完了,大家要想練練手的話我們有hdu1754..

題目傳送門在這裡:的中文題目..)

最後附對於此題,本蒟蒻弱智的模板:

#include 

#include

#define gc getchar()

const

int inf=~0u>>1;

class binary_tree4

inline

int max(const

int &a,const

int &b)

inline

int min(const

int &a,const

int &b)

inline

int gnum()

void init()

}void update(int x,int s)

}int ask(int l,int r)

return ans;

}public:

void work()}}

};int main()

o(∩_∩)o收工~

模板篇 樹狀陣列們(四)

這是第四篇樹狀陣列了。我們之前講過樹狀陣列的以下幾大作用 單點加區間查 不會的話 區間加單點查 不會的話 區間加區間查 不會的話 然而上面的會不會的無所謂啊。因為上面我們查的都是區間和性質的東西。就是用字首和差分能減出來的東西 而我們今天要做的,是 單點修改,區間查詢最大值 在這裡,我要給大家講一下...

模板篇 樹狀陣列們(三)

upd 本篇有了乙個更通 hui 俗 se 易 nan 懂的講解,大家可以移步這裡圍觀 使用了latex推柿子,帶給你不一樣的清新體驗 ok,以上兩期稍稍講了一下樹狀陣列的基本功能。當然,把樹狀陣列拉出來不能只有這兩個功能對不對。不然網上都有怎麼把你們忽悠來看嘛 樹狀陣列還是有兩把刷子的 非戰鬥人員...

模板篇 樹狀陣列們(一)

以下文章邏輯混亂,請確保精神正常後再 為什麼要搞樹狀陣列?快。lowbit是什麼呢?lowbit i 指的是i在二進位制表示下最低位的1及其後的所有0組成的值 比如36 在二進位制下是100100,最低位的1我加粗了,代表了4,所以lowbit 36 就是4。從圖上可以看出,對於樹狀陣列上的節點,第...