제출 #1244722

#제출 시각아이디문제언어결과실행 시간메모리
1244722borisAngelovCat in a tree (BOI17_catinatree)C++20
100 / 100
315 ms37676 KiB
#include <bits/stdc++.h> using namespace std; const int maxn = 200005; const int LOG = 18; const int inf = 1e9 + 7; int n, d; vector<int> g[maxn]; int jump[maxn][LOG]; int depth[maxn]; vector<int> tour; void dfs(int node, int par, int d) { tour.push_back(node); depth[node] = d; jump[node][0] = par; for (auto to : g[node]) { if (to != par) { dfs(to, node, d + 1); } } } void buildSparse() { for (int log = 1; log < LOG; ++log) { for (int i = 1; i <= n; ++i) { jump[i][log] = jump[jump[i][log - 1]][log - 1]; } } } int findLCA(int x, int y) { if (depth[x] < depth[y]) swap(x, y); int diff = depth[x] - depth[y]; for (int i = 0; i < LOG; ++i) { if ((diff & (1 << i)) != 0) { x = jump[x][i]; diff -= (1 << i); if (diff == 0) break; } } if (x == y) return x; for (int i = LOG - 1; i >= 0; --i) { if (jump[x][i] != jump[y][i]) { x = jump[x][i]; y = jump[y][i]; } } return jump[x][0]; } int dist(int x, int y) { int lca = findLCA(x, y); return depth[x] + depth[y] - 2 * depth[lca]; } int sz[maxn]; int parent[maxn]; bool seen[maxn]; void dfsInit(int node, int par) { sz[node] = 1; for (auto to : g[node]) { if (to != par && seen[to] == false) { dfsInit(to, node); sz[node] += sz[to]; } } } int findCentroid(int node, int par, int whole) { for (auto to : g[node]) { if (to != par && seen[to] == false && sz[to] > whole / 2) { return findCentroid(to, node, whole); } } return node; } int decompose(int node) { dfsInit(node, -1); //cout << "decompose with " << node << " :: " << sz[node] << endl; int c = findCentroid(node, -1, sz[node]); seen[c] = true; //cout << "found " << c << endl; for (auto to : g[c]) { if (seen[to] == false) { int newC = decompose(to); parent[newC] = c; } } return c; } int minDist[maxn]; void fastIO() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); } int main() { fastIO(); cin >> n >> d; for (int i = 2; i <= n; ++i) { int par; cin >> par; ++par; g[i].push_back(par); g[par].push_back(i); //cout << "edge " << i << " " << par << endl; } dfs(1, 1, 0); buildSparse(); sort(tour.begin(), tour.end(), [&](int x, int y) { return depth[x] > depth[y]; }); for (int i = 1; i <= n; ++i) { parent[i] = -1; minDist[i] = inf; } decompose(1); /*for (int i = 1; i <= n; ++i) { cout << i << " :: " << parent[i] << endl; }*/ int ans = 0; for (auto node : tour) { int currentNode = node; int currMin = inf; while (currentNode != -1) { currMin = min(currMin, dist(node, currentNode) + minDist[currentNode]); currentNode = parent[currentNode]; } //cout << "on " << node << " -> " << currMin << endl; if (currMin < d) { continue; } //cout << "mark " << node << endl; ++ans; currentNode = node; while (currentNode != -1) { minDist[currentNode] = min(minDist[currentNode], dist(node, currentNode)); currentNode = parent[currentNode]; } } cout << ans << endl; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...