Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ACLを使ってみよう!

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for shirotsume4 shirotsume4
December 02, 2022

 ACLを使ってみよう!

Avatar for shirotsume4

shirotsume4

December 02, 2022
Tweet

More Decks by shirotsume4

Other Decks in Education

Transcript

  1. ACLとは?  AtCoder Libraryの略称  AtCoder社によって用意された、競技プログラミングのためのC++ライブラリ集  AtCoderで出題される問題には、ACLを使うことを想定した問題が多い!  →より高速に解けたり、楽に実装出来たりする

     →覚えていて損はない!  AtCoderやyukicoderなどではサーバー側にACLがインストールされているため、 ライブラリを貼る必要もない!  公式ではC++だけだが、他の言語でも有志によりほぼ同じ機能を持つ移植版が リリースされている  →調べてみよう!  https://atcoder.github.io/ac-library/document_ja/index.html
  2. 使ってみよう! AtCoder Library Practice Contest A: Disjoint Set Union 

    N 頂点 0 辺の無向グラフに Q 個のクエリが飛んできます。処理してください。  0 u v: 辺(u,v)を追加する。  1 u v: u,v が連結ならば 1、そうでないなら 0 を出力する。
  3. ACLを導入しよう!  まずは https://atcoder.jp/posts/517 からzipファイルをダウンロード  実行したいcppファイルと同じ場所にzipの中のatcoderフォルダを置いて、コ ンパイルを  g++

    main.cpp -std=c++14 -I .  とするとうまく動きます  Coderunner等自動実行環境を使っている人は、そちらの設定でコンパイルコマ ンドを変えてやってみましょう
  4. ACLのアルゴリズム一覧  DSU (Union-Find)  Fenwick Tree  Segtree 

    LazySegtree  Math  SCC  Two-SAT  Maxflow  Mincostflow  convolution  string
  5. DSU Union-Find  DSU(Union-Find)とは、無向グラフに対して以下のクエリを高速に処理するこ とができるデータ構造  1: 辺の追加  2:

    2つの頂点u, vが連結か(すなわち、いくつかの辺をたどってuからvへ移動 できるか)  愚直にやると幅優先探索などでΘ(QN)とかになるが、DSUを使えばΘ(Qα(N))に なる(めちゃくちゃ早い!)
  6. Fenwick Tree(BIT)  長さNの配列Aがある。初め、Aの各要素は0。  Aに対し、以下のクエリを処理する。  1 i x:

    A[i] += x  2 l r: A[l] + A[l + 1] + … + A[r - 1] を求める  愚直にやると、Θ(QN)かかる  クエリ1が無ければ累積和でできるが、変更があるので難しい  Fenwick Tree(BIT)というデータ構造で、Θ(QlogN)でできる!
  7. Segtree  長さNの配列Aがある。  Aに対し、以下のクエリを処理する。  1 i x: A[i]

    を x に変更  2 l r: A[l] ⊕ A[l + 1] ⊕ … ⊕ A[r - 1] を求める  Segtreeでは、行う二項演算⊕を自分で決めることができる!  例えば、max, min, xor, gcd, … などなど  モノイドであればよい(結合法則a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ cが成り立って、単位元 があればセグ木に乗る)
  8. LazySegtree  長さNの配列Aがある。  Aに対し、以下のクエリを処理する。  1 i x: A[i]

    を x に変更  2 l r: A[l] ⊕ A[l + 1] ⊕ … ⊕ A[r - 1] を求める  3 l r: A[x]を f(A[x]) に置き換える、という操作をl <= x < rを満たす各xについて 行う  Segtreeとの違いは、クエリ3  区間に対し変更する操作を行うことができる  変更を行う関数mapping、関数を合成をするcomposition、何もしないのと同様 の関数を表す id を定義する必要がある
  9. 遅延セグ木、追記  初めてで使い方が分からなければ、ARMERIA/AtCoder LibraryのLazy Segtree の使い方を参考にしましょう  多くの実装では関数Fなどを新たに型を作って実装しています(F f, S

    sのよう に)が、区間加算や区間更新でこのような工夫が必要になることは少ないです。  単に、両方intやllでやればよいです  Range Affine Range Sum ( https://atcoder.jp/contests/practice2/tasks/practice2_k )など難しいものにな ると必要になってきます。解きごたえのある問題ですが、解説をみながらやる のは非常にいい勉強になると思います
  10. Math / pow_mod, inv_mod  pow_mod … x^n mod p

    を返す。  ll ans = pow_mod(x, n, p);  inv_mod … モジュロ逆数、すなわちmod p 上で 1/xに当たる数を返す  ll ans = inv_mod(x, p);  確率/期待値を mod998244353で求めてくださいと言われた時に役立つ
  11. Math/ CRT  CRT(中国剰余定理)  「x を m_i で割ったあまりが r_i」という条件が複数与えられた時、それらを

    すべて満たすxが存在するか判定し、あるなら1つ出力  pair<ll, ll> ans = crt(vector<ll> r, vector<ll> m);  解があれば、ansの1つはyとなる。zはmの最小公倍数  無ければ(0, 0) が返る
  12. Math/ floor_sum  σ 𝑖=0 𝑛 −1 𝑓𝑙𝑜𝑜𝑟(𝑎𝑖+𝑏 𝑚 )

    を求める。  ll ans = floor_sum(n, m, a, b);  計算量はO(log(n + m + a + b))  !!!ここにyukicoderでの出題例が!!!  https://yukicoder.me/problems/no/1899
  13. Two-SAT  Two-SATを解きます  すなわち、n個のtrue/falseで表せる条件x_0, x_1, … x_{n – 1}があり、いくつ

    かの条件が以下の形式で与えられたとする  x_i = (true/false)またはx_j = (true/false)  この条件を全て満たすxの真偽割り当てがあるか判定し、あるなら実際に1つ求 める  これはsccを応用したアルゴリズムで解いている
  14. Two-SAT 問題例  1 から N までの番号のついた N 本の旗があります. これらの旗を,数直線状

    に設置します.  旗 i は,座標 X iまたは 座標 Y iに設置することができます. ただし,どの 2 つの旗についても,その間の距離が D 以上である必要があります.  N 本の旗を設置することが可能かどうか判定し,可能であるならば,実際に置 き方を 1 つ示してください.  Xをtrue、Yをfalseと考える。距離がD未満になるような置き方はできないので、 それを考えて条件式を作っていく
  15. Convolution  FFT(NTT)による畳み込みを行う。  2つの多項式 f(x) = a_0 + a_1x

    + a_2x^2 + … a_nx^nと  g(x) = b_0 + b_1x + b_2x^2 + … b_mx^mがあったとき、f(x) * g(x)の各係数を求 める  普通にやるとΘ(NM)だが、Convolutionを使うと、Θ((N + M)log(N + M))になる  ACLの実装では、NTTを用いることで、mod p 上で上のことを正確に行う。  もともと結果がlong longに収まるとわかっているなら、convolution_llを用い るとあまりを取らずにやってくれる
  16. String/ suffix_array  文字列Sのsuffix_arrayを求める。  すなわち、S[0:n]、S[1:n] … S[n – 1:

    n]を辞書順に並べ替えたとき、S[i:n]がp[i] 番目に来るとする。これで定まる順列p[i]を求める  普通にやるとO(N^2)とかになりますが、これはO(NlogN)でできます  例えばappleだと、’apple’, ‘pple’, ‘ple’, ‘le’, ‘e’ がそれぞれ辞書順で何番目に なるかを求める。よって、(0, 4, 3, 2, 1) が返される
  17. String/ lcp_array  文字列のlcp_arrayとは、以下のように決まる配列P  P[i] = S[i:n] と S[i

    + 1:n]のLCPの長さ、すなわち前何文字が同じか  こちらも普通にやるとO(N^2)とかO(N^3)だが、ACLの実装ではO(N)で返される
  18. String/ Z_algorithm  文字列Sに対して、以下の配列Pを求める。  P[i] = S[0:n]とS[i:n]のLCPの長さ  以上述べた3種の文字列アルゴリズムでは、文字列のマッチング(文字列の中

    に、指定された文字列が含まれるか判定する)を高速に行うことができる  各アルゴリズムでできることの違いがよくわかっていないです…  そもそもハッシュでいいのでは、という思いもあり…(help!)