#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>> {
vector<segment_tree<max_t<int>>> chs;
for (int &i : adj[u]) {
chs.push_back(self(self, i));
}
segment_tree<max_t<int>> dp(sz[u] + 1, 0);
for (auto &ndp : chs) {
if (ndp.size() > dp.size() - 1) {
swap(dp, ndp);
}
vector<int> qvals;
for (int i = 0; i < ndp.size(); ++i) {
if (max(i + 1, d - i) < dp.size() - 1) {
qvals.push_back(dp.query(max(i + 1, d - i), dp.size() - 1 - 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() - 1) {
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);
for (int i = dp.size() - 1; i >= 1; --i) {
dp.set(i, dp.at(i - 1));
}
dp.set(0, 0);
return dp;
};
segment_tree<max_t<int>> dp = dfs(dfs, 0);
cout << dp.query(0, dp.size() - 1 - 1) << '\n';
}
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |