### dragoon's blog

By dragoon, history, 7 weeks ago, ,

Let's discuss the solutions.

How to solve B?

• +43

 » 7 weeks ago, # |   +44 How to solve H?
•  » » 7 weeks ago, # ^ | ← Rev. 2 →   +30 The key idea is to solve the problem without the strings "A" and then iterate over the number of them to glue to words ending with 'S'.And that subproblem is just some tedious case-handling:"..SA" + "D..": connect min($cnt_{SA}$, $cnt_{D}$) words to each other and subtract 1 if the set of indices of words ending with "SA" is equal to the set of indices of words starting with "D" (they got connected into a cycle). Same for "..S" + "AD..".And the only case left is when all words got connected into one cycle. Subtract 1 more if all possible connections are made, union of sets "D.." and "AD.." is equal to union of sets "..S" and "..SA" and there were no subtractions in previous connections.
•  » » 7 weeks ago, # ^ |   +52 Copy-paste from recent JAG contest.
•  » » » 7 weeks ago, # ^ |   +16 :(
 » 7 weeks ago, # |   +21 How to solve E?
•  » » 7 weeks ago, # ^ | ← Rev. 3 →   +60 Let's emulate the specified in the statements algorithm, but instead of removing overlapped boxes on step 2, we will just skip this step and then for every processed box we will first check whether it was removed previously or not. If it "was removed" just skip it, otherwise select it.So we need to maintain some structure that allows adding new selected boxes and checking whether the current box overlaps enough with previously added boxes.Let's divide all the plane into square cells with side equal to $S$ and store these cells in the unordered map, i.e. for each non-empty cell we will store a vector of selected boxes inside this cell. Then to check if current box is overlapped with some other, we just need to go over 9 neighboring cells and calculate IOU with all boxes in those cells straightforwardly. The key idea is that there will be not too many boxes inside one cell because every pair of selected boxes should have $IOU <= threshold$.It passed in 1.2 out of 10 sec.
•  » » » 7 weeks ago, # ^ |   +9 Thanks!)
 » 7 weeks ago, # |   0 How to solve K, L?
 » 7 weeks ago, # | ← Rev. 2 →   +29 We upsolved B like this: lets fix set of vertices. Initially it is only 0 in the set. Than make our moves find minimum digit that is adjacent to vertices of our set. Create new set with vertices that is adjacent to previous set by edges with minimum digit. Clearly this is best way we can go. Just save sets to some map and if your current set is equall to some previous set => you have cycle or if you have 1 in you current set => you have way withot cycles. Of course initially we remove vertices that can't be reached from 1 by reversed edges. By the way I don't know why it is not TL.
•  » » 7 weeks ago, # ^ |   +32 I think I can make a case where this TLs :) Create a few loops of zeros with coprime lengths, and add zero edges from 0 to one vertex in each loop, and one edges from one vertex in each loop to 1.
•  » » » 7 weeks ago, # ^ |   0 Thanks, now I see
 » 7 weeks ago, # | ← Rev. 2 →   0 Can anyone please link a pdf of the problem-set?
•  » » 7 weeks ago, # ^ |   +8
 » 7 weeks ago, # |   +18 Any ideas about F?
 » 7 weeks ago, # | ← Rev. 4 →   0 B: We didn't have time to implement but I think the following should work:1) Remove all vertices that don't have path to 1(bfs/dfs)2) Add edge 1->1 by number 03) From each vertex choose only edges with minimal digits4) Sort (in at most n iteration, each iteration O(n log n) or O(n) if counting sort) vertices by distance to 1: First, each vertex is in group by its outgoing digits. Then in each iteration vertex i is less the vertex j iff i was less than j on previous iteration or if they were equal and now min(class[outgoing[i]]) < min(class[outgoing[j]).5) Choose path from 0 greedily. You'll get some preperiod and period which you need to convert to A/B
•  » » 7 weeks ago, # ^ | ← Rev. 3 →   +16 Sounds too complicated Remove all edges going to vertices having no path to 2. Maintain the set of vertices you can be at aftet going through $k$ edges. It's easy to recalculate the set for $k+1$ in O(V+E), just consider all minimal edges and go through them. Build the set for $k=V+eps$, if you notice during the computation that vertex 2 is in your set at some point, restore the path and break. Otherwise the answer is cyclic. Restore path for any vertex in set with $k=V+eps$, and find preperiod and period there.
•  » » » 7 weeks ago, # ^ | ← Rev. 2 →   0 I didn't understand. What is V+eps?
•  » » » » 7 weeks ago, # ^ |   0 Number of edges to go through. If you go at least $V+1$ edges you will surely find the cycle, which is what we want to.
•  » » » 7 weeks ago, # ^ |   0 Ok, that's indeed somewhat easier, thanks
 » 7 weeks ago, # |   0 We tried solving B by keeping a set of vertices and iteratively advance with the lowest digit edge (only considering vertices that reach $1$). We do this iteration $4n$ times, and then extrapolate the rational resulting number. However, it gives WA 7. Any ideas why?Code
•  » » 7 weeks ago, # ^ |   +10 Integer overflow at Out function. My solution is the same as you, but I iterated $3n+50$ times.
•  » » » 7 weeks ago, # ^ |   +10 Great, thanks...
•  » » 7 weeks ago, # ^ |   0 I did the same bug, but I fixed it during contest :)
 » 7 weeks ago, # |   +8 How to solve C?
•  » » 7 weeks ago, # ^ | ← Rev. 2 →   +30 $dp[i][j]$ — the minimum price to put $i$ letters and have latest $j$ letters copied. $j = 0$ means the last move was to put a single letter.From any state $dp[i][j]$ you can put a single letter and go to $dp[i + 1][0]$, paste the current copied string into its next occurence and go to $dp[nxt[i][j]][j]$ (filling the rest of letters by single insertions) or copy the next $k$ letters from somewhere earlier (if there was such an occurence), paste it immediately and go to $dp[i + k][k]$.$nxt$ and occurrence checks can obviously be precomputed with z-function.
•  » » » 7 weeks ago, # ^ | ← Rev. 2 →   +16 I think TL on C was absurdly tight. We had simple $O(n^2)$ DP solution with substring hashes computed with suffix arrays, but it gets TLE verdict (due to cache-friendliness issues).Code: https://pastebin.com/JPLWrVyS Lines 147-177 is the actual DP
•  » » » 7 weeks ago, # ^ |   0 We got TLE with exactly this approach, could you share your code?
•  » » » » 7 weeks ago, # ^ | ← Rev. 3 →   +16 works in 7.5 secondscode
 » 7 weeks ago, # |   +8 How to solve I?
•  » » 7 weeks ago, # ^ |   +34 It works for all $n$. Just build a staircase: [(1, 1)] [(1, 2) (2, 2)] [(1, 3) (2, 3) (3, 3)] [(1, 4) (2, 4) (3, 4) (4, 4)] ... (i, j) means, you place block of $(i, j)$, with $j$ in the opposite side of sight.
 » 7 weeks ago, # |   +52 Unfortunately, H was in recent MW camp, I think that's why it was solved so much.
 » 7 weeks ago, # | ← Rev. 2 →   +2 Any fast solution for K? I solved it using small-to-large in 1.973s, I assume it was not intended.
•  » » 7 weeks ago, # ^ |   +32 My solution works in 0.879s. I think it was intended O(N log N) with small-to-large.
•  » » » 7 weeks ago, # ^ |   0 My small-to-large solution is $O(N \log^2{N})$. How one can achieve $O(N \log{N})$?
•  » » » » 7 weeks ago, # ^ |   +24 For every component you can maintain number of numbers such that x and x+1 are in that component, answer for that component is size — that number. Question is how to avoid using sets. Well, you can have vectors and then when you are moving x from smaller vector to larger one, first you need to check if x+1 is there. Same for x-1. Code#include using namespace std; typedef long long ll; typedef double lf; typedef long double Lf; typedef pair pii; typedef pair pll; #define TRACE(x) cerr << #x << " " << x << endl #define FOR(i, a, b) for (int i = (a); i < int(b); i++) #define REP(i, n) FOR(i, 0, n) #define all(x) (x).begin(), (x).end() #define _ << " " << #define fi first #define sec second #define mp make_pair #define pb push_back const int MAXN = 200100; struct UnionFind { vector v[MAXN]; int connected[MAXN]; int par[MAXN]; void init() { REP(i, MAXN) { v[i].clear(); par[i] = i; connected[i] = 0; v[i].pb(i); } } void merge(int a, int b) { a = par[a]; b = par[b]; if ((int)v[a].size() < (int)v[b].size()) swap(a, b); for (auto x : v[b]) { if (par[x - 1] == a) connected[a]++; if (par[x + 1] == a) connected[a]++; v[a].pb(x); } for (auto x : v[b]) par[x] = a; connected[a] += connected[b]; } int get(int x) { x = par[x]; return (int)v[x].size() - connected[x]; } }; UnionFind Uf; int n, ans[MAXN]; vector v[MAXN]; void dfs(int node, int par) { for (auto nnode : v[node]) { if (nnode == par) continue; dfs(nnode, node); Uf.merge(node, nnode); } ans[node] = Uf.get(node); } void solve(int test) { scanf("%d",&n); Uf.init(); REP(i, MAXN) v[i].clear(); REP(i, n - 1) { int a, b; scanf("%d %d",&a,&b); v[a].pb(b); v[b].pb(a); } dfs(1, -1); printf("Case #%d: ", test); FOR(i, 1, n + 1) printf("%d ",ans[i]); puts(""); } int main() { int t; cin >> t; REP(i, t) solve(i + 1); return 0; } 
•  » » 7 weeks ago, # ^ | ← Rev. 2 →   +13 We have just LCA + DSU that passes in 1 second. I guess you can make it sub-nlogn but idk if that will be faster :)
•  » » » 7 weeks ago, # ^ |   0 Could you please elaborate your solution in detail?
•  » » » » 7 weeks ago, # ^ |   +18 Well, it's just that $i$ and $i + 1$ merge their segments at $lca(i, i + 1)$. With this fact you simply collect all the updates you'll need to do in each vertex and do one dfs. The answer for vertex $v$ is $1 + \sum \limits_{u \in g_v} ans_u$ minus the number of updates in $v$.Also I just realized I don't even use dsu here.
 » 7 weeks ago, # |   +28 What about J? Is this test valid? 2 message A { required A name1 = 1; required string name2 = 100; } message B { required B name1 = 1; required string name2 = 101; } 1 A B At least, there is no such case in testset, but I think I didn't found anything against it in statement. Answer formally is compatible. Also, what's the reason of giving 6-page statement with about 10% useful information?
•  » » 7 weeks ago, # ^ |   0 We didn't find anything about it, either, so we assumed this stuff can happen (and I just checked that the protobuf compiler consumes this description just fine). I don't know if I'm more relieved or surprised that such a case was not in the testset. :P
 » 7 weeks ago, # |   +20 What's a reliable way to ask for clarifications during the OpenCups? We asked a couple of clarifying questions through the Yandex system within 2h of the start of the contest and we never got a response. :(
•  » » 7 weeks ago, # ^ |   +16 I thought that asking Snark in Telegram was most reliable, but that also didn't work today.
 » 7 weeks ago, # |   +3 BTW are the authors of this contest known? I saw at least three problems that made me interested by the context :)
 » 7 weeks ago, # |   +16 How to solve G?
•  » » 7 weeks ago, # ^ | ← Rev. 3 →   0 Let $v_1, v_2, \ldots, v_k$ be the sons of the root. Let $l_i$ be the depth of the deepest taken vertex in the subtree of $v_i$ (possibly $l_i = 0$). It turns out that the second player wins if and only if $max(l_1, \ldots, l_k) = max_2(l_1, \ldots, l_k)$. It can be proved using the fact that we can remove all vertices which are ends of some diameter (at least I thought this proof is correct during the contest). Implementation is pretty standard, complexity is $O(n \cdot log(n))$.
•  » » » 7 weeks ago, # ^ |   0 Could you clarify the implementation? In my code I had to divide by numbers that could be zero modulo 10**9+7, but luckily there were no such testcases.
•  » » » » 7 weeks ago, # ^ | ← Rev. 5 →   +10 I do it too, but I think its easy not to do it. When I maintain these arrays $arr_{v, j}$ — how many ways to choose in the subtree of $v$ vertices with the deepest one in the depth $j$, I need to multiply some suffix by $x$, so I divide some prefix by $x$, but I can just not to do it if $x = 0$, adding some parameter "what suffix is turned to $0$", recalculating this after every action with the array.When I calculate the answer, I can do it too, storing the number of ways in the subtrees which cant provide another depth $d$ separately and using prefix sums for others.
•  » » » » » 7 weeks ago, # ^ |   0 Right, that should work!
 » 7 weeks ago, # |   +16 Can someone explain how to solve problem L?
•  » » 7 weeks ago, # ^ |   0 Code brute -> notice the pattern.
•  » » 7 weeks ago, # ^ | ← Rev. 3 →   +21 Print 2 when n or m is 1, else 2n + 2m — 4.
•  » » » 7 weeks ago, # ^ |   -18 can you explain whay answer is 8 + 2 * (a — 3 + b -3 ) for a > 2 and b > 2