pbds初探


今年暑假外校集訓的時候一道題標算是最短路擴展,然而std用的是pbds,於是就產生了研究的興趣。結果那個標程我現在死都找不到了233

定義:

 在知乎上看到有oier去年向CCF發了郵件,得到的回復是pbds庫可以用,但是不能寫這句話:

using namespace __gnu_pbds;

 

存圖為證。

--------------------------------------------------------------------------原答案分割線--------------------------------------------------------------------------------------------------------------------------------------

pbds是一個封裝了眾多高效又實用(相對於STL)的數據結構的庫,包括堆,平衡樹,哈希表等。然而目前仍然不清楚NOIP中能否使用。在CCF2011年發布的關於NOI系列賽編程語言使用限制的規定中明確規定C/C++程序禁止使用內嵌匯編和以下划線開頭的庫函數或宏(自己定義的除外),然而在WC2015營員交流中一位同學卻說pbds在NOI系列賽事中可以使用,這就造成了現在的這種尷尬境地。

由於本人實在蒟蒻,加上pbds的平衡樹在維護有序序列時對存在重復元素的情況維護難度較大,且該問題用STL中的vector就可以妥善解決,(之前自己智障),在此只介紹pbds中堆的用法。

用法:

由於bits/stdc++.h不覆蓋pbds,使用時需加上#include<ext/pb_ds/priority_queue.hpp>和using namespace __gnu_pbds;(gnu前兩條下划線)。(命名空間不能使用)

注意:pbds的堆在定義時不需要vector<int>。

定義一個int類型的小根堆:__gnu_pbds::priority_queue<int,greater<int>,TAG>pq;

TAG指明了所用堆的類型,共有以下幾種:

pairing_heap_tag:配對堆

thin_heap_tag:斐波那契堆

binomial_heap_tag:二項堆

binary_heap_tag:二叉堆

如果是大根堆的話只需要去掉greater<int>即可,也可以定義結構體類型或者其他類型,只要重載了<運算符就可以使用。

這些堆普遍支持push,pop,top和join操作。最后一個操作是將兩個堆合並,使用方法:a.join(b);//將堆b合並至堆a中

配對堆和斐波那契堆的理論復雜度均十分優異,push,top,join都能做到均攤O(1),pop能做到O(logn)。

二項堆的各種操作復雜度都是O(logn)。二叉堆的復雜度不知,但實際運行速度極慢,反而不如std和手寫堆,不知是何原因,不建議使用。

拿一道最短路例題來測試一下各種堆的速度吧:

例題:

Luogu P3371 【模板】單源最短路徑 題目鏈接

題意:給定一張n個點,m條邊的有向圖和起點s,要求輸出s到每個點的最短距離,若不可達輸出2147483647。

數據范圍:n<=10000,m<=500000。

題解:SPFA或dijkstra堆優化。

配對堆:756ms

斐波那契堆:664ms

二項堆:812ms

二叉堆:1516ms+3TLE

TAG留空(我也不知道這是什么騷操作):586ms

基本符合理論復雜度。在平時或者考場上時建議使用配對堆或斐波那契堆或者直接留空


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM