제출 #1296221

#제출 시각아이디문제언어결과실행 시간메모리
1296221avighnaCat in a tree (BOI17_catinatree)C++20
51 / 100
372 ms589824 KiB
#include <bits/stdc++.h> namespace algo { template <typename T> class segment_tree { private: std::size_t n; std::vector<T> seg; struct accessor { segment_tree &st; std::size_t i; accessor(segment_tree &st, std::size_t i) : st(st), i(i) {} accessor &operator=(const T &x) { st.set(i, x); return *this; } accessor &operator+=(const T &x) { return *this = st.at(i) + x; } accessor &operator-=(const T &x) { return *this = st.at(i) - x; } operator T() const { return st.at(i); } friend std::ostream &operator<<(std::ostream &os, const accessor &acc) { return os << T(acc); } }; public: segment_tree(std::size_t n) : n(n), seg(2 * n) {} segment_tree(const segment_tree &other) : n(other.n), seg(other.seg) {} segment_tree() : n(0) {} segment_tree(std::size_t n, const T &x) : n(n), seg(2 * n) { for (std::size_t i = n; i < 2 * n; ++i) { seg[i] = x; } for (std::size_t i = n - 1; i > 0; --i) { seg[i] = seg[2 * i] + seg[2 * i + 1]; } } segment_tree(const std::vector<T> &vals) : n(vals.size()), seg(2 * n) { set(vals); } void set(std::size_t i, const T &x) { for (seg[i += n] = x, i /= 2; i > 0; i /= 2) { seg[i] = seg[2 * i] + seg[2 * i + 1]; } } T query(std::size_t l, std::size_t r) const { T ans_l = T{}, ans_r = T{}; for (l += n, r += n + 1; l < r; l /= 2, r /= 2) { if (l & 1) ans_l = ans_l + seg[l++]; if (r & 1) ans_r = seg[--r] + ans_r; } return ans_l + ans_r; } std::size_t size() const { return n; } const T &at(std::size_t i) const { return seg[n + i]; } accessor operator[](std::size_t i) { return accessor(*this, i); } }; template <typename T> requires std::is_arithmetic_v<T> struct max_t { T x; constexpr max_t() : x(std::numeric_limits<T>::min()) {} constexpr max_t(const T &x) : x(x) {} constexpr max_t operator+(const max_t &other) const { return std::max(x, other.x); } constexpr operator T() const { return x; } constexpr bool operator==(const max_t &other) const { return x == other.x; } constexpr bool operator!=(const max_t &other) const { return x != other.x; } }; } // namespace algo using namespace std; using namespace algo; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, d; cin >> n >> d; vector<vector<int>> adj(n); for (int i = 1, p; i < n; ++i) { cin >> p; adj[p].push_back(i); } if (d >= n) { cout << "1\n"; return 0; } vector<int> sz(n); auto dfs_sz = [&](auto &&self, int u) -> void { sz[u] = 1; for (int &i : adj[u]) { self(self, i); sz[u] += sz[i]; } }; dfs_sz(dfs_sz, 0); auto dfs = [&](auto &&self, int u) -> segment_tree<max_t<int>> { segment_tree<max_t<int>> dp(sz[u], 0); for (int &i : adj[u]) { segment_tree<max_t<int>> _ndp = self(self, i); segment_tree<max_t<int>> ndp(_ndp.size() + 1, 0); for (int i = 1; i <= _ndp.size(); ++i) { ndp[i] = int{_ndp.at(i - 1)}; } if (ndp.size() > dp.size()) { swap(dp, ndp); } vector<int> qvals; for (int i = 0; i < ndp.size(); ++i) { if (max(i + 1, d - i) < dp.size()) { qvals.push_back(dp.query(max(i + 1, d - i), dp.size() - 1)); } else { qvals.push_back(0); } } for (int i = 0; i < ndp.size(); ++i) { if (max(i, d - i) < ndp.size()) { dp[i] = int{dp.at(i)} + int{ndp.query(max(i, d - i), ndp.size() - 1)}; } } for (int i = 0; i < ndp.size(); ++i) { dp[i] = max(int{dp.at(i)}, int{ndp.at(i)}); } for (int i = 0; i < ndp.size(); ++i) { if (max(i + 1, d - i) < dp.size()) { dp[i] = max(int{dp.at(i)}, qvals[i] + int{ndp.at(i)}); } } } dp[0] = max(int{dp.at(0)}, (d < sz[u] ? int{dp.at(d)} : 0) + 1); return dp; }; segment_tree<max_t<int>> dp = dfs(dfs, 0); cout << dp.query(0, dp.size() - 1) << '\n'; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...