Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
doubling_fold.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2
3/// @brief ダブリング(モノイド合成)
4/// @tparam Monoid 合成するモノイド
5/// @tparam Log ダブリングの深さ
6template<typename Monoid, int Log>
8 using Type=typename Monoid::Type;
9 DoublingFold()=default;
10
11 /// @brief コンストラクタ
12 /// @param p 各頂点の遷移先
13 /// @param v 各頂点の値
14 /// @note O(N Log)
15 DoublingFold(const vector<int>& p, const vector<Type>& v) {
16 int n=p.size();
17 dat=vector<vector<Type>>(Log+1,vector<Type>(n,Monoid::id()));
18 nxt=vector<vector<int>>(Log+1,vector<int>(n));
19 for(int i=0; i<n; i++) dat[0][i]=v[i], nxt[0][i]=p[i];
20 for(int i=1; i<=Log; i++) for(int j=0; j<n; j++) {
21 nxt[i][j]=nxt[i-1][nxt[i-1][j]];
22 dat[i][j]=Monoid::op(dat[i-1][j], dat[i-1][nxt[i-1][j]]);
23 }
24 }
25
26 /// @brief モノイド積
27 /// @brief 頂点 start から k 回遷移したときのモノイド積を返す
28 /// @note O(Log)
29 Type fold(int start, ll k) {
30 Type ret= Monoid::id();
31 for(int b=0; k>0; b++,k>>=1) if(k&1) {
32 ret=Monoid::op(ret,dat[b][start]);
33 start=nxt[b][start];
34 }
35 return ret;
36 }
37
38 /// @brief 頂点 start から k 回遷移した先の頂点を返す
39 /// @note O(Log)
40 int next(int start, ll k) {
41 for(int b=0; k>0; b++,k>>=1) if(k&1) start=nxt[b][start];
42 return start;
43 }
44
45private:
46 vector<vector<Type>> dat;
47 vector<vector<int>> nxt;
48};
ダブリング(モノイド合成)
DoublingFold()=default
DoublingFold(const vector< int > &p, const vector< Type > &v)
コンストラクタ
Type fold(int start, ll k)
モノイド積
int next(int start, ll k)
頂点 start から k 回遷移した先の頂点を返す