もうひとつのるま式全方位木 DP
前提知識
もうひとつのるま式全方位木 DP とは
るま式全方位木 DP では逆元が必要でした. しかし全方位木 DP は両側累積和を用いることで逆元を使わずに書くことが出来ます. そこで,るま式全方位木 DP を少し改造することで逆元が必要無いように書き換えたものを,ぼくが勝手にもうひとつのるま式全方位木 DP と呼んでいます.
実装例
std::vector<std::map<int, value>> dp(n); auto solve = [&](auto&& solve, int v, int par, bool flag) -> value { if(dp[v].count(par)) return dp[v][par]; value res = id; // id = 単位元 if(par == -1 or flag) { std::vector<value> ret; for(int i = 0; i < g[v].size(); i++) { int to = g[v][i]; if(to == par) continue; ret.push_back(solve(solve, to, v, flag)); } std::vector<value> R(ret.size() + 1, id); for(int i = R.size() - 1; i > 0; i--) R[i - 1] = merge(R[i], ret[i - 1]); if(par == -1) { value L = id; for(int i = 0; i < g[v].size(); i++) { int to = g[v][i]; dp[v][to] = merge(L, R[i + 1]); L = merge(L, ret[i]); } } res = R[0]; } else { solve(solve, v, -1, flag); return solve(solve, v, par, flag); } return dp[v][par] = res; }; solve(solve, 0, -1, true); for(int i = 0; i < n; i++) cout << solve(solve, i, -1, false) << endl;