Submit Search
Upload
色々なダイクストラ高速化
•
41 likes
•
25,317 views
Y
yosupo
Follow
色々なダイクストラ高速化とありますが結局はRadixHeapの解説です
Read less
Read more
Technology
Report
Share
Report
Share
1 of 35
Download now
Download to read offline
Recommended
直前合宿 講義スライド
直前合宿 講義スライド
tozan gezan
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
shindannin
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
Masaki Hara
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
Takuya Akiba
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
Kensuke Otsuki
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
Takuya Akiba
Recommended
直前合宿 講義スライド
直前合宿 講義スライド
tozan gezan
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
shindannin
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
Masaki Hara
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
Takuya Akiba
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
Kensuke Otsuki
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
Takuya Akiba
目指せグラフマスター
目指せグラフマスター
HCPC: 北海道大学競技プログラミングサークル
ウェーブレット木の世界
ウェーブレット木の世界
Preferred Networks
最大流 (max flow)
最大流 (max flow)
HCPC: 北海道大学競技プログラミングサークル
Rolling hash
Rolling hash
HCPC: 北海道大学競技プログラミングサークル
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
Takuya Akiba
動的計画法を極める!
動的計画法を極める!
HCPC: 北海道大学競技プログラミングサークル
双対性
双対性
Yoichi Iwata
平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズム
Takuya Akiba
直交領域探索
直交領域探索
okuraofvegetable
Binary indexed tree
Binary indexed tree
HCPC: 北海道大学競技プログラミングサークル
様々な全域木問題
様々な全域木問題
tmaehara
Union find(素集合データ構造)
Union find(素集合データ構造)
AtCoder Inc.
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
Takuya Akiba
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Takuya Akiba
Convex Hull Trick
Convex Hull Trick
HCPC: 北海道大学競技プログラミングサークル
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
Takuya Akiba
全域木いろいろ
全域木いろいろ
HCPC: 北海道大学競技プログラミングサークル
文字列アルゴリズム
文字列アルゴリズム
HCPC: 北海道大学競技プログラミングサークル
大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端
Takuya Akiba
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
Hibiki Yamashiro
WUPC2012
WUPC2012
Dai Hamada
冬のLock free祭り safe
冬のLock free祭り safe
Kumazaki Hiroki
More Related Content
What's hot
目指せグラフマスター
目指せグラフマスター
HCPC: 北海道大学競技プログラミングサークル
ウェーブレット木の世界
ウェーブレット木の世界
Preferred Networks
最大流 (max flow)
最大流 (max flow)
HCPC: 北海道大学競技プログラミングサークル
Rolling hash
Rolling hash
HCPC: 北海道大学競技プログラミングサークル
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
Takuya Akiba
動的計画法を極める!
動的計画法を極める!
HCPC: 北海道大学競技プログラミングサークル
双対性
双対性
Yoichi Iwata
平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズム
Takuya Akiba
直交領域探索
直交領域探索
okuraofvegetable
Binary indexed tree
Binary indexed tree
HCPC: 北海道大学競技プログラミングサークル
様々な全域木問題
様々な全域木問題
tmaehara
Union find(素集合データ構造)
Union find(素集合データ構造)
AtCoder Inc.
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
Takuya Akiba
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Takuya Akiba
Convex Hull Trick
Convex Hull Trick
HCPC: 北海道大学競技プログラミングサークル
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
Takuya Akiba
全域木いろいろ
全域木いろいろ
HCPC: 北海道大学競技プログラミングサークル
文字列アルゴリズム
文字列アルゴリズム
HCPC: 北海道大学競技プログラミングサークル
大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端
Takuya Akiba
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
Hibiki Yamashiro
What's hot
(20)
目指せグラフマスター
目指せグラフマスター
ウェーブレット木の世界
ウェーブレット木の世界
最大流 (max flow)
最大流 (max flow)
Rolling hash
Rolling hash
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
動的計画法を極める!
動的計画法を極める!
双対性
双対性
平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズム
直交領域探索
直交領域探索
Binary indexed tree
Binary indexed tree
様々な全域木問題
様々な全域木問題
Union find(素集合データ構造)
Union find(素集合データ構造)
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Convex Hull Trick
Convex Hull Trick
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
全域木いろいろ
全域木いろいろ
文字列アルゴリズム
文字列アルゴリズム
大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
Similar to 色々なダイクストラ高速化
WUPC2012
WUPC2012
Dai Hamada
冬のLock free祭り safe
冬のLock free祭り safe
Kumazaki Hiroki
「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online
「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online
Hisatoshi Onishi
Jpoug 20120721
Jpoug 20120721
Koji Shinkubo
SVM -R-
SVM -R-
Yuu Kimy
Material
Material
_TUNE_
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
mametter
虫食算を作るアルゴリズム 公表Ver
虫食算を作るアルゴリズム 公表Ver
Kensuke Otsuki
マルチコアを用いた画像処理
マルチコアを用いた画像処理
Norishige Fukushima
USP友の会勉強会、状態遷移図の巻
USP友の会勉強会、状態遷移図の巻
Ryuichi Ueda
HPC Phys-20201203
HPC Phys-20201203
MITSUNARI Shigeo
“Stay Right”ペンテスト体験:SANS Holiday Hack Challenge 2017の解説 & Walkthrough
“Stay Right”ペンテスト体験:SANS Holiday Hack Challenge 2017の解説 & Walkthrough
Isaac Mathis
ICFP2009-いかにして我々は戦ったか
ICFP2009-いかにして我々は戦ったか
ina job
Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based language
Taku Miyakawa
㉑CSSでアニメーション!その2
㉑CSSでアニメーション!その2
Nishida Kansuke
Arduinoでプログラミングに触れてみよう 続編
Arduinoでプログラミングに触れてみよう 続編
Hiromu Yakura
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
Kimikazu Kato
Gorinphp0729
Gorinphp0729
akitsukada
Gorinphp0729
Gorinphp0729
akitsukada
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
AtCoder Inc.
Similar to 色々なダイクストラ高速化
(20)
WUPC2012
WUPC2012
冬のLock free祭り safe
冬のLock free祭り safe
「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online
「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online
Jpoug 20120721
Jpoug 20120721
SVM -R-
SVM -R-
Material
Material
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
虫食算を作るアルゴリズム 公表Ver
虫食算を作るアルゴリズム 公表Ver
マルチコアを用いた画像処理
マルチコアを用いた画像処理
USP友の会勉強会、状態遷移図の巻
USP友の会勉強会、状態遷移図の巻
HPC Phys-20201203
HPC Phys-20201203
“Stay Right”ペンテスト体験:SANS Holiday Hack Challenge 2017の解説 & Walkthrough
“Stay Right”ペンテスト体験:SANS Holiday Hack Challenge 2017の解説 & Walkthrough
ICFP2009-いかにして我々は戦ったか
ICFP2009-いかにして我々は戦ったか
Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based language
㉑CSSでアニメーション!その2
㉑CSSでアニメーション!その2
Arduinoでプログラミングに触れてみよう 続編
Arduinoでプログラミングに触れてみよう 続編
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
Gorinphp0729
Gorinphp0729
Gorinphp0729
Gorinphp0729
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
Recently uploaded
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
CRI Japan, Inc.
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
iPride Co., Ltd.
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
iPride Co., Ltd.
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
WSO2
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
iPride Co., Ltd.
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
Toru Tamaki
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
Toru Tamaki
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
CRI Japan, Inc.
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
atsushi061452
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
sn679259
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Hiroshi Tomioka
Recently uploaded
(11)
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
色々なダイクストラ高速化
1.
ダイクストラ法高速化いろいろ @yosupot
2.
ダイクストラ法とは • 単一始点最短経路を求める有名なアルゴリズム • 普通のヒープを使って計算量はO((V+E)logV) •
O(V^2)もありますが今回は触れません
3.
ダイクストラを高速化したい!
4.
ダイクストラが遅くて困る時の原因
5.
ダイクストラが遅くて困る時の原因 1. 解法が間違っている
6.
ダイクストラが遅くて困る時の原因 1. 解法が間違っている 2. 他の部分が遅い
7.
ダイクストラが遅くて困る時の原因 1. 解法が間違っている 2. 他の部分が遅い 3.
ジャッジがPKU
8.
ダイクストラは速い!!! 甘えるな!!!!
9.
ご静聴 ありがとうございました 参考:http://www.slideshare.net/qnighy/ss-15312828
10.
でも本当に高速化はいらない? • 最小費用流とかも速くなる • めちゃ定数倍が厳しいのがあったら役に立つかも •
そもそも速度は速いに越したことはない
11.
高速化(基本編)
12.
1 const int
V = 10000, INF = 1<<28; 2 using P = pair<int, int>; 3 vector<P> G[V]; // pair<辺の距離, 行き先の頂点> 4 T dist[V]; // dist[i]はsから頂点iへの最短距離が入る 5 bool used[V]; 6 void dijkstra(int s) { // s:始点 7 fill_n(dist, V, INF); 8 fill_n(used, V, false); 9 priority_queue<P, vector<P>, greater<P>> q; 10 q.push(P(0, s)); 11 while (!q.empty()) { 12 T d; int t;//d:sからの距離 t:行き先 13 tie(d, t) = q.top(); q.pop(); 14 if (used[t]) continue; //もう既に探索済みか 15 used[t] = true; dist[t] = d; 16 for (P e: G[t]) { 17 18 q.push(P(d+e.first, e.second)); 19 } 20 } 21 } 普通のDijkstra
13.
1 const int
V = 10000, INF = 1<<28; 2 using P = pair<int, int>; 3 vector<P> G[V]; // pair<辺の距離, 行き先の頂点> 4 T dist[V]; // dist[i]はsから頂点iへの最短距離が入る 5 bool used[V]; 6 void dijkstra(int s) { // s:始点 7 fill_n(dist, V, INF); 8 fill_n(used, V, false); 9 priority_queue<P, vector<P>, greater<P>> q; 10 q.push(P(0, s)); 11 while (!q.empty()) { 12 T d; int t;//d:sからの距離 t:行き先 13 tie(d, t) = q.top(); q.pop(); 14 if (used[t]) continue; //もう既に探索済みか 15 used[t] = true; dist[t] = d; 16 for (P e: G[t]) { 17 18 q.push(P(d+e.first, e.second)); 19 } 20 } 21 } 普通のDijkstra ここに
14.
1 const int
V = 10000, INF = 1<<28; 2 using P = pair<int, int>; 3 vector<P> G[V]; // pair<辺の距離, 行き先の頂点> 4 T dist[V]; // dist[i]はsから頂点iへの最短距離が入る 5 bool used[V]; 6 void dijkstra(int s) { // s:始点 7 fill_n(dist, V, INF); 8 fill_n(used, V, false); 9 priority_queue<P, vector<P>, greater<P>> q; 10 q.push(P(0, s)); 11 while (!q.empty()) { 12 T d; int t;//d:sからの距離 t:行き先 13 tie(d, t) = q.top(); q.pop(); 14 if (used[t]) continue; //もう既に探索済みか 15 used[t] = true; dist[t] = d; 16 for (P e: G[t]) { 17 18 q.push(P(d+e.first, e.second)); 19 } 20 } 21 } 普通のDijkstra if (dist[e.second] <= d+e.first) continue; こう
15.
高速化(基本編) • 単純な枝狩り 非常に有名 •
priority_queueに入れる前にその時点での最短距離をチェック • めちゃ効果が高い これを行うと何十倍も速くなる問題も
16.
高速化(基本編) • 単純な枝狩り 非常に有名 •
priority_queueに入れる前にその時点での最短距離をチェック • めちゃ効果が高い これを行うと何十倍も速くなる問題も http://abc012.contest.atcoder.jp/tasks/abc012_4 ABC12D 避けられない運命 UTPC2013L 1円ロード http://utpc2013.contest.atcoder.jp/tasks/utpc2013_12 この枝刈りを使わないと厳しい問題もある (そもそもこれはO((V+E)logV)ダイクストラは想定解ではない)
17.
ここからは、いくつか特殊なケースでの 高速化を紹介します
18.
辺の長さが小数(doubleとか)の場合
19.
辺の長さが小数(doubleとか)の場合 このスライドはここで(本当に)終了です。 ご静聴ありがとうございました
20.
辺の長さが整数 • 辺の長さが 1
のみ → BFSをしろ • 辺の長さが 0 or 1 のみ → 0-1BFSをしろ • 辺の長さが100以下とか→キューを101個用意しろ
21.
• 辺の長さが大きい場合 • RadixHeapという高速なHeapがあります •
このスライドの本題です 辺の長さが整数
22.
RadixHeapとは • 非負整数専用Heap • 最後に取り出した値より小さな値を入れられない •
計算量はならしO(logD) (D: 入れたい値の最大値) • 定数倍がめちゃ軽い • 64bit版も出来ますが, 今回は32bitで説明します
23.
1 int bsr(uint
x) { 2 if (x == 0) return -1; 3 return 31-__builtin_clz(x); 4 } 5 6 struct RadixHeapInt { 7 vector<uint> v[33]; 8 uint last, sz; 9 RadixHeapInt() { 10 last = sz = 0; 11 } 12 void push(uint x) { 13 assert(last <= x); 14 sz++; 15 v[bsr(x^last)+1].push_back(x); 16 } 17 uint pop() { 18 assert(sz); 19 if (!v[0].size()) { 20 int i = 1; 21 while (!v[i].size()) i++; 22 uint new_last = 23 *min_element(v[i].begin(), v[i].end()); 24 for (uint x: v[i]) { 25 v[bsr(x^new_last)+1].push_back(x); 26 } 27 last = new_last; 28 v[i].clear(); 29 } 30 sz--; 31 v[0].pop_back(); 32 return last; 33 } 34 }; ソースコード 実装は重くない (skew heapよりは重い)
24.
• Bit Search
Reverseの略 • 一番左の1のbitが(0-indexedで)何番目かを数える • ロバストなlog2(x)とも考えられる • __builtin_clz(x)は31-bsr(x)を返してくれる便利関数 1 int bsr(uint x) { 2 if (x == 0) return -1; 3 return 31-__builtin_clz(x); 4 } bsrとは? • 0b00010000 -> 4 • 0b01011001 -> 6 • 0b11111111 -> 0 • 0b00000000 -> -1 (builtin_clzに0を渡すとぶっ壊れるため場合分け)
25.
push 1 void push(uint
x) { 2 assert(last <= x); 3 sz++; 4 v[bsr(x^last)+1].push_back(x); 5 } • RadixHeapでは値がpushされるとbsr(x^last)+1によって33 個のバッファに振り分けられる • 逆にd個目のバッファの中の値xについてd==bsr(x^last)+1 というのはいつでも(pushした後もpopした後も)33個の バッファの中の全ての値について成立していなければいけな い • push関数自体はv[bsr(x^last)+1]に値を放り込むだけでいい
26.
push v[i] 中身(last=12) 0 0b00001100 1
0b00001101 2 0b0000111x 3 該当なし 4 該当なし 5 0b0001xxxx 6 0b001xxxxx 7 0b01xxxxxx 8 0b1xxxxxxx 右はlast=12(0b00001100)の時の例 重要な性質 • lastに関わらずlastと同じ値はv[0]に入る • 逆にv[0]にはlastと同じ値しか入れない • v[i+1]の値は必ずv[i]の値より大きい • v[3]とv[4]は12未満の要素しか入れない 1 void push(uint x) { 2 assert(last <= x); 3 sz++; 4 v[bsr(x^last)+1].push_back(x); 5 } →必ず空
27.
pop 1 uint pop()
{ 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 } v[0]に値が入っている場合 v[0]に値が入っていない場合
28.
pop 1 uint pop()
{ 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 } v[0]に値が入っている場合 → 中身は必ずlastと同じ値(つまり最小)なので取り出せばいい v[0]に値が入っていない場合
29.
pop 1 uint pop()
{ 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 } v[0]に値が入っている場合 → 中身は必ずlastと同じ値(つまり最小)なので取り出せばいい v[0]に値が入っていない場合 → v[i+1]の値 v[i]の値であることに注目
30.
pop 1 uint pop()
{ 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 } v[0]に値が入っている場合 → 中身は必ずlastと同じ値(つまり最小)なので取り出せばいい v[0]に値が入っていない場合 → v[i+1]の値 v[i]の値であることに注目 → v[1], v[2], v[3] … と順に中身があるかチェック 中身があったらその中での最小値が全体での最小値
31.
pop 1 uint pop()
{ 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 } v[0]に値が入っている場合 → 中身は必ずlastと同じ値(つまり最小)なので取り出せばいい v[0]に値が入っていない場合 → v[i+1]の値 v[i]の値であることに注目 → v[1], v[2], v[3] … と順に中身があるかチェック 中身があったらその中での最小値が全体での最小値 ただしそのまま取り出すだけではダメ 値の再振り分けが必要
32.
pop 引き続きv[0]に値が入っていない場合を考える v[i]から新しく最小値new_lastを取り出したとする → i, i+1,
i+2 … bit目はlastとnew_lastで変わらない → v[i+1], v[i+2], v[i+3] … に入る値の範囲は変わらない! → bsr(last^new_last) は当然 i-1 更に、v[i]から新しく取り出したならv[0], v[1], … v[i-1]は空 → 結局再振り分けするのはv[i]の中身だけでいい! 1 uint pop() { 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 }
33.
pop そして、v[i]の値とnew_lastはi-1, i, i+1,
… bit目は等しい → 再振り分けされたv[i]の値は必ずv[j](j < i)へ行く (i, i+1, i+2 … bit目はlastとnew_lastで変わらない事とnew_lastはv[i]に属すことから) → 一つの値について、それが再振り分けされる回数は必ず32回以内 → ならし計算量がO(logD)になることが保証される 1 uint pop() { 2 assert(sz); 3 if (!v[0].size()) { 4 int i = 1; 5 while (!v[i].size()) i++; 6 uint new_last = 7 *min_element(v[i].begin(), v[i].end()); 8 for (uint x: v[i]) { 9 v[bsr(x^new_last)+1].push_back(x); 10 } 11 last = new_last; 12 v[i].clear(); 13 } 14 sz--; 15 v[0].pop_back(); 16 return last; 17 }
34.
• unsigned long
long版を作ればpair<int, int>を入れられ るのでダイクストラに使用できます • unsigned int版を改造してもダイクストラに使用できます →こちら(https://github.com/yosupo06/Algorithm/ blob/master/Cpp/Data%20Structure/RadixHeap.h)
35.
まとめ • そもそもダイクストラの高速化が必要になることは ほとんど無い • それでも速度が欲しかったり、最小費用流を高速化 したかったり、高速なHeapが欲しいなら RadixHeapはサイコー
Download now