CSES - Fixed-Length Paths II

Authors: Andi Qu, Benjamin Qi

With Centroid Decomposition

Time Complexity: O(Nlog2N)\mathcal O(N \log^2 N)

This solution is a simple extension of CSES Fixed-Length Paths I's solution.

Since we want to count the number of paths of length between aa and bb instead of a fixed length kk, a node with depth dd in uu's ii-th child's subtree will contribute x=adbdcnti1[x]\sum_{x = a - d}^{b - d}\texttt{cnt}_{i - 1}[x] paths instead of cnti1[kd]\texttt{cnt}_{i - 1}[k - d] paths to the answer.

This is a range sum, so we can use any range-sum data-structure (e.g. a BIT) to query and update cnt\texttt{cnt} efficiently. This adds an additional logN\log N factor to the complexity.

C++

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n, a, b;
vector<int> graph[200001];
int subtree[200001];
ll ans = 0, bit[200001];
int mx_depth;

Faster Solution

Time Complexity: O(N)\mathcal O(N)

We use the same idea as the above solution but with prefix sums instead of a BIT and with small-to-large merging in a single DFS instead of centroid decomposition. This is because we can merge two prefix sum arrays AA and BB in O(min(A,B))\mathcal O(\min(|A|, |B|)) time.

If we let did_i denote the maximum depth in node ii's subtree, then the number of operations SS that our algorithm performs can be calculated by

S=i=1N[1+ci’s children(1+dc)maxci’s children(dc)]=N+i=1N(ci’s children(1+dc)(di1))\begin{aligned} S &= \sum_{i = 1}^N \left[1 + \sum_{c \in i\text{'s children}} (1 + d_c) - \max_{c \in i \text{'s children}}(d_c) \right]\\ &= N + \sum_{i = 1}^N \left(\sum_{c \in i\text{'s children}} (1 + d_c) - (d_i - 1) \right) \end{aligned}

Now,

i=1Nci’s children(1+dc)=N1+i=2Ndi\sum_{i = 1}^N \sum_{c \in i\text{'s children}} (1 + d_c) = N - 1 + \sum_{i = 2}^N d_i

and

i=1N(di1)=i=1Ndi+N\sum_{i = 1}^N -(d_i - 1) = -\sum_{i = 1}^N d_i + N

Summing these two expressions and adding NN gives

S=3N1d1S = 3N - 1 - d_1

which is O(N)\mathcal O(N). Below is Ben's code implementing this idea:

C++

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using db = long double; // or double, if TL is tight
using str = string; // yay python!
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using pd = pair<db, db>;

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!