這是第四篇樹狀陣列了。。
我們之前講過樹狀陣列的以下幾大作用:
單點加區間查 不會的話->
區間加單點查 不會的話->
區間加區間查 不會的話->
然而上面的會不會的無所謂啊。。。
因為上面我們查的都是區間和性質的東西。。(就是用字首和差分能減出來的東西_ (:з」∠) _)
而我們今天要做的,是:
單點修改,區間查詢最大值
在這裡,我要給大家講一下時間複雜度,不過你們要答應我我說完不要走
我們拿能幹查詢最大值的兩樣其他東西來比,線段樹和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。從圖上可以看出,對於樹狀陣列上的節點,第...