### Zlobober's blog

By Zlobober, history, 4 years ago, translation,

Unfortunately Codeforces fails to show formulas in an editorial and I can't even press on "Preview" button :( While it doesn't work as intended, I put a bit ugly pdf-version of an editorial here. Unfortunately without model solution sources yet.

Russian editorial

English editorial

• +35

 » 4 years ago, # | ← Rev. 2 →   +33 " ... Pascal triangle and started to investigate properties of binomial coefficients located on the same line. That was the wrong way :)"This is also a good way, the "Pascal triangle" tells me that we are finding coefficients of xc in (xa + xb)0 + (xa + xb)1 + (xa + xb)2 + ..., then it is easy to see S(C) = S(C-A) + S(C-B).
 » 4 years ago, # |   +3 Want to share my solution to E. It's seems to be isomorphic to what is written in the editorial but If I was to implement what is in editorial I would get much harder solution.Let's root the tree in any vertex, now suppose pair of vertices u,v (au < av). If v is not in the subtree of u then it adds 1 to answer of all vertices in subtree of u. If it in the subtree of to — some direct child of u then it adds 1 to answer of all vertices except vertices in subtree of to which means add 1 everywhere and add -1 to subtree of toNow process vertices u in decreasing order of its value in groups of vertices of same value: you need to know how many vertices v in each subtree (it's a range query) and outside of subtree of u (it's all others), and add answers to some subtrees. Adding to subtrees is either adding to a range in tin order or may be done offline. Codeclass TaskE { public: vector> g; vector tin, tout; int timer = 0; vector parent; void dfs(int v, int p) { tin[v] = timer++; for (int to: g[v]) { if (to != p) { parent[to] = v; dfs(to, v); } } tout[v] = timer; } void dfs2(int v, int p, vector& ans) { for (int to: g[v]) { if (to != p) { ans[to] += ans[v]; dfs2(to, v, ans); } } } void solve(std::istream& in, std::ostream& out) { using Tree = TopDownSumSegmentTree; int n; in >> n; g.resize(n); tin.resize(n); tout.resize(n); parent.resize(n); vector a(n); for (int i: range(n)) { in >> a[i]; } for (int i: range(n - 1)) { int u, v; in >> u >> v; --u, --v; g[u].push_back(v); g[v].push_back(u); } vector almostAnswer(n); Tree cntBig(n); vector indices(n); for (int i: range(n)) { indices[i] = i; } sort(indices, [&](int l, int r) { return a[l] > a[r]; }); dfs(0, -1); for (int i = 0; i < n;) { int j = i; while (j < n && a[indices[i]] == a[indices[j]]) { ++j; } for (int k: range(i, j)) { int v = indices[k]; int64_t othersBig = i; for (int to: g[v]) { if (to == parent[v]) { continue; } int64_t bigInSubtree = cntBig.getResult(tin[to], tout[to]); othersBig -= bigInSubtree; almostAnswer[0] += bigInSubtree; almostAnswer[to] -= bigInSubtree; } almostAnswer[v] += othersBig; } for (int k: range(i, j)) { int v = indices[k]; cntBig.update(tin[v], tin[v] + 1, 1); } i = j; } dfs2(0, -1, almostAnswer); int best = 0; for (int i: range(n)) { if (almostAnswer[i] < almostAnswer[best]) { best = i; } } out << best + 1<< ' ' << almostAnswer[best] << "n"; } };