Pythonにmultisetが欲しいという意見がよくある e.g. ABC170 E
だいたいのことがheapqとの組み合わせでできる
heapq
O(logn)で要素の挿入
O(1)で最小値の取得
Pythonにmultisetが欲しいという意見がよくある e.g. ABC170 E
だいたいのことがheapqとの組み合わせでできる
heapq
O(logn)で要素の挿入
O(1)で最小値の取得
ABC170 問題E Smart Infants
20万個の数値が20万個の集合を20万回動き回る。
このとき「集合の最大値」の最小値を各移動ごとに求めよ、という問題。
コンテスト中の思考
当然、各移動ごとに各集合に対してO(N)の処理をしたらTLEするだろう。
RBST (Randomized Binary Search Tree)
k 番目の値を高速に取り出せるデータ構造のまとめ - BIT上二分探索や平衡二分探索木など - Qiita
AVL木
k 番目に小さい値を取得可能な集合を管理するデータ構造 - kazuma8128’s blog
部分和の計算と要素の更新の両方を効率的に行える木構造
フェニック木 - Wikipedia
蟻本ではBinary lndexed Treeと呼ばれてる
BITと略される
fenwick tree
まとめ
np.array はリストに比べて2倍ほど要素アクセスが遅い
numpyの添え字アクセスは遅い
累積和を計算するコードを作りnumbaでコンパイルするとnp.arrayを使った側が速くなった
速くなりすぎ感があるので今度もう少しちゃんと調べたい
数え上げテクニック集
http://degwer.hatenablog.com/entry/20171220 DEGwer
2 状態をまとめる
DPは全探索の高速化
値域が狭い(問題の制約で狭めてある)時や、定義域がやたら広い(部分集合の全体2^2000とか)時に、値域と定義域を交換する問題変換が有効なケースがある
フェニック木
値の集合を添え字が値であるような配列に1が立ってるもので表現する
動的計画法
値域が定義域より狭い時に、定義域の中で最大の値を見つける代わりに、値域の中で制約を満たす最大の添え字を見つける
N個のものと大小比較をして、条件を満たすものの個数を知りたい
大小比較を各々のものに対して行うとO(N)
しかし、特に多くのクエリを発行するケースで、O(NQ)では遅すぎることがある。
N個のものをフェニック木に入れておけば、範囲和を取ることで対数オーダーで条件を満たすものの個数が得られる
値域を定義域にする
点(x, y)がN個ある時に長方形区間0≤x<Tx,0≤y<Tyの点の数を数える問題
0≤x,y<Mとする
特に各点(xi,yi)について j∑[xj<xi][yj<yi]を計算する場合
素朴にループで書くとO(N^2)なのでNが大きい時に工夫が必要
二次元の片方を時間軸にする
固定個数の値の列が与えられた時に、その区間に対して演算することが対数時間でできるデータ構造
AtCoderにおいて結構頻出する
プログラミングコンテストでのデータ構造 秋葉 拓哉 p.33~
値の更新 O(logN)
区間に対する演算 O(logN)
要求
削除可能な集合{x}から不等号で表現された条件x≥x0を満たすものを列挙したい
例えばソート済み配列なら二分探索で不等号条件を満たす境界を対数オーダーで見つけられる
しかし配列からの削除は線形オーダー掛かってしまう
削除が高速なリンクトリストでは、ランダムアクセスができないので二分探索できない
計算機科学および離散数学における列の転倒(てんとう、英: inversion)は、その列の項の対であって、それらの項の成分が自然な順番から外れているようなものを言う。
inv(A)=#{(Ai,Aj)∣i<jandAi>Aj}
結合した列x+yの転倒数はそれぞれの転倒数fと頻度表cから求められる ACLPC L PAST4K
from 第四回 アルゴリズム実技検定
PAST4K
K - 転倒数
考えたこと
転倒数
Q - Flowers
二つの数列が与えられて、片方の数列の単調増加列になるような部分列すべての中で、もう一つの数列で与えられたスコアの合計が最大になるものを選ぶ問題
サンプルの小さい問題に関してはこれで解ける
このmaxの部分が素朴にO(N)だと全体でN^2になって、10^10だから間に合わない
そこでlog Nでmaxを計算できるアルゴリズムを使う
様々なアルゴリズムを AtCoder 側で実装した
https://atcoder.jp/posts/517
AtCoder Library Practice Contest
練習用コンテストで一通りACした解説
とりあえず確認してみたら1/3から1/2くらい既に実装してあった。今はリポジトリにバラバラに散らばってるので後でACLと同じディレクトリ構造にしてMITライセンスにしとこう。
6/25に書いたもの:
5週間ほどatcoderをやってみて、自分がどういう学び方をしているのかを言語化できたのでメモ
緑になった時点で読み返してツイートしよう
→7/5に緑になったので整理加筆してツイートした
まずはコンテストに参加する
1: アルゴリズムを工夫する
2a: PyPyで走らせる
配列の添え字アクセスが多いなどのとき
2b: Numpyを使う
配列に対する一括操作が多い時
自分がABC171 Fの時に書いたコードを再利用するために整理してて、ついでにmaspy法と速度比較してみたらmaspy法をNumbaでコンパイルしたものが一番速かった。
100万件からの組み合わせテーブル作成が、特定のnに対してワンショットなら35msec、階乗と逆数階乗を先に作って使い回すなら49msec(準備に30msec)
i8[:]
to i8[::1]
numba contiguous array
In numba world, np.concatenate can not concatenate np.array and list. (as of numba 0.50)
np.concatenate(): expecting a non-empty tuple of arrays, got Tuple(array(int64, 1d, C), list(int64))
numba
recursion-in-numba Notebook :: Anaconda Cloud
Note that an explicit type signature is required at the moment for Numba's recursion support to work
atcoder F - Pond Skater ABC170
解説の通り位置と向きを頂点としてダイクストラ法 #長方形グラフ探索
1コストでKマス進めるのに1歩ずつ進むのを疑問に思って解説を無視してみたが、ダメだった
探索の1ステップでKマス進むとTLEになるため、1マスずつ探索する必要がある
素直にnp.arrayにできるならそれが楽でいいのだけど、実用上は「キーが整数である辞書で、値は可変長のリスト。リストの要素は2整数のタプル」みたいな複雑な型のことがあり(実話)これをnp.arrayに詰め込もうとしてエンバグするのは不毛。
この型は、生のPythonの辞書やリストのままではnumbaでうまく扱えないのだが、typed.Dictとtyped.Listを使えば実現できる。問題はこれを関数に渡す時に関数の型シグニチャがどうなるか。
OK
adding a signature would involve implementing it for Numba
http://numba.pydata.org/numba-doc/latest/extending/index.html
And http://numba.pydata.org/numba-doc/latest/extending/overloading-guide.html
NG
OK
numba