제출 #960988

#제출 시각아이디문제언어결과실행 시간메모리
960988Andrei_ierdnACat Exercise (JOI23_ho_t4)C++17
100 / 100
145 ms62544 KiB
#include <iostream> #include <iomanip> #include <vector> using namespace std; int n, i, h[200010], u, v, p[200010], depth[200010]; vector<int> nb[200010]; long long dp[200010]; namespace euler { int t, sparseMin[19][400010], firstPoz[200010]; void appendNode(int node) { sparseMin[0][++t] = depth[node]; } void appendNodeFirst(int node) { appendNode(node); firstPoz[node] = t; } void computeSparse() { for (int i = 1; (1 << i) <= t; i++) { for (int j = 1; j + (1 << i) - 1 <= t; j++) { sparseMin[i][j] = min(sparseMin[i-1][j], sparseMin[i-1][j+(1<<(i-1))]); } } } int querySparseMin(int l, int r) { int len = 31 - __builtin_clz(r-l+1); return min(sparseMin[len][l], sparseMin[len][r-(1<<len)+1]); } int getNodeDist(int a, int b) { int minDepth = querySparseMin(min(firstPoz[a], firstPoz[b]), max(firstPoz[a], firstPoz[b])); return depth[a] + depth[b] - 2*minDepth; } } namespace dsu { int nrdsu, dsu[200010], maxi[200010]; void init() { nrdsu = n; for (int i = 1; i <= n; i++) { dsu[i] = -1; maxi[i] = i; } } int getRoot(int node) { if (dsu[node] < 0) return node; return dsu[node] = getRoot(dsu[node]); } bool dsuMerge(int a, int b) { a = getRoot(a); b = getRoot(b); if (a == b) return false; if (dsu[a] > dsu[b]) swap(a, b); dsu[a] += dsu[b]; dsu[b] = a; maxi[a] = max(maxi[a], maxi[b]); maxi[b] = 0; nrdsu--; return true; } } void dfs1(int node) { euler::appendNodeFirst(node); for (auto x : nb[node]) { if (!p[x]) { p[x] = node; depth[x] = depth[node] + 1; dfs1(x); euler::appendNode(node); } } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cin >> n; for (i = 1; i <= n; i++) { cin >> h[i]; } for (i = 1; i < n; i++) { cin >> u >> v; u = h[u]; v = h[v]; nb[u].push_back(v); nb[v].push_back(u); } p[1] = 1; depth[1] = 1; dfs1(1); euler::computeSparse(); dsu::init(); dp[1] = 0; for (int i = 2; i <= n; i++) { for (auto x : nb[i]) { if (x <= i) { int bigboy = dsu::maxi[dsu::getRoot(x)]; dp[i] = max(dp[i], euler::getNodeDist(i, bigboy) + dp[bigboy]); dsu::dsuMerge(i, x); } } } cout << dp[n]; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...