Repository: cpinitiative/usaco-guide
Pull request #5277: Random
Author: login: RyanFu08
Created: 2025-04-08T22:06:52Z | Merged: 2025-04-11T01:47:34Z

_Place an "x" in the corresponding checkbox if it is done or does not apply to this pull request._

- [x] I have tested my code.
- [x] I have added my solution according to the steps [here](https://usaco.guide/general/adding-solution#steps).
- [x] I have followed the code conventions mentioned [here](https://usaco.guide/general/adding-solution/#code-conventions).
  - I understand that if it is clear that I have not attempted to follow these conventions, my PR will be closed.
  - If changes are requested, I will re-request a review after addressing them.
- [x] I have linked this PR to any issues that it closes.

Another day, another module ... hopefully this topic is interesting enough for a module?


Diff:
diff --git a/content/6_Advanced/assets/random-graph.png b/content/6_Advanced/assets/random-graph.png
new file mode 100644
index 00000000000..4546daeb4a9
Binary files /dev/null and b/content/6_Advanced/assets/random-graph.png differ
diff --git a/content/6_Advanced/random.mdx b/content/6_Advanced/random.mdx
new file mode 100644
index 00000000000..4e0776208b9
--- /dev/null
+++ b/content/6_Advanced/random.mdx
@@ -0,0 +1,347 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems.
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S \cdot \left(N\log A + d(A)^2 + \sqrt{A}\right)\right)$
+, with the log factor occurring due to GCD computation, and the sqrt due to factoring.
+
+```cpp
+#include <bits/stdc++.h>
+using namespace std;
+
+const int MAX_N = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+long long a[MAX_N], dv[MAX_N], cnt[MAX_N];
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+
+	int n;
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+
+	long long ans = 0;
+	for (int s = 0; s < S; s++) {
+		long long x = a[rng() % n];
+		int ind = 0;
+		for (int d = 1; 1ll * d * d <= x; d++) {
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		}
+
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+
+	cout << ans << '\n';
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The graph was generated for the probability of answering $4\cdot10^4$ queries correctly in a row. This assumption is reasonable because the test data consists of only 1 large test case.
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+const int MAX_N = 5e5 + 1;
+const int S = 150;
+const us INF = 65535;
+
+us va[MAX_N][S];
+int n, m, c[MAX_N];
+
+namespace SGT {
+const int L = 1 << 19;
+us seg[2 * L][S];
+
+void build() {
+	for (int i = L - 1; i; i--) {
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+	}
+}
+
+void point_update(int idx, int v) {
+	int pos = L + idx;
+	for (int j = 0; j < S; j++) { seg[pos][j] = va[v][j]; }
+	pos /= 2;
+	while (pos) {
+		int left = pos * 2, right = left + 1;
+		for (int j = 0; j < S; j++) { seg[pos][j] = min(seg[left][j], seg[right][j]); }
+		pos /= 2;
+	}
+}
+
+inline us range_min(int l, int r, int j) {
+	us res = INF;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int MAX_N = 5e5 + 1;
+int f[MAX_N], depth[MAX_N], heavy[MAX_N], head[MAX_N], pos[MAX_N], cp = 0;
+vector<int> adj[MAX_N];
+
+void clear(int n) {
+	for (int i = 0; i < n; i++) { adj[i].clear(); }
+	cp = 0;
+}
+
+void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int nxt : adj[v]) {
+		if (nxt != f[v]) {
+			f[nxt] = v;
+			depth[nxt] = depth[v] + 1;
+
+			int csz = dfs(nxt);
+			sz += csz;
+			if (csz > msz) {
+				msz = csz;
+				heavy[v] = nxt;
+			}
+		}
+	}
+
+	return sz;
+}
+
+void decompose(int v, int h) {
+	head[v] = h;
+	pos[v] = cp++;
+	for (int j = 0; j < S; j++) SGT::seg[SGT::L + pos[v]][j] = va[c[v]][j];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int nxt : adj[v]) {
+		if (nxt == f[v] || nxt == heavy[v]) continue;
+		decompose(nxt, nxt);
+	}
+}
+
+inline void init() {
+	memset(heavy, -1, sizeof(heavy));
+	dfs(0);
+	decompose(0, 0);
+}
+
+us path_min(int a, int b, int j) {
+	us res = INF;
+	while (head[a] != head[b]) {
+		if (depth[head[a]] > depth[head[b]]) swap(a, b);
+		res = min(res, SGT::range_min(pos[head[b]], pos[b], j));
+		b = f[head[b]];
+	}
+
+	if (depth[a] > depth[b]) swap(a, b);
+	res = min(res, SGT::range_min(pos[a], pos[b], j));
+	return res;
+}
+}  // namespace HLD
+
+void solve() {
+	cin >> n >> m;
+	for (int i = 0; i < n; i++) cin >> c[i];
+	HLD::clear(n);
+	for (int i = 1; i < n; i++) {
+		int u, v;
+		cin >> u >> v;
+		u--, v--;
+		HLD::add_edge(u, v);
+	}
+
+	HLD::init();
+	SGT::build();
+
+	int cnt = 0;
+	for (int i = 0; i < m; i++) {
+		int tp;
+		cin >> tp;
+		if (tp == 1) {
+			int x, y;
+			cin >> x >> y;
+			x ^= cnt;
+			y ^= cnt;
+			SGT::point_update(HLD::pos[x - 1], y);
+		} else {
+			int a, b, cc, d;
+			cin >> a >> b >> cc >> d;
+			a ^= cnt, b ^= cnt, cc ^= cnt, d ^= cnt;
+			a--, b--, cc--, d--;
+
+			long long c1 = 0, c2 = 0;
+			for (int j = 0; j < S; j++) {
+				c1 += HLD::path_min(a, b, j);
+				c2 += HLD::path_min(cc, d, j);
+			}
+
+			if (c1 < c2) {
+				cnt++;
+				cout << "Yes\n";
+			} else {
+				cout << "No\n";
+			}
+		}
+	}
+}
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+
+	mt19937 rng(1434);
+	for (int i = 1; i < MAX_N; i++) {
+		for (int j = 0; j < S; j++) { va[i][j] = rng() % (INF + 1); }
+	}
+
+	int test_num;
+	cin >> test_num;
+	for (int t = 0; t < test_num; t++) { solve(); }
+}
+```
+
+## Problems
+
+Some of the listed problems do not require random algorithms as a solution, but can be made significantly easier through using random algorithms.
+
+<Problems problems="general" />
diff --git a/content/6_Advanced/random.problems.json b/content/6_Advanced/random.problems.json
new file mode 100644
index 00000000000..b3df6f8bd9d
--- /dev/null
+++ b/content/6_Advanced/random.problems.json
@@ -0,0 +1,86 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Hard",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "fb-2024practiceC",
+      "name": "Fall in Line",
+      "url": "https://www.facebook.com/codingcompetitions/hacker-cup/2024/practice-round/problems/C",
+      "source": "MHC",
+      "difficulty": "Easy",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "none"
+      }
+    },
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/problemset/problem/840/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-442E",
+      "name": "Gena and Second Distance",
+      "url": "https://codeforces.com/contest/442/problem/E",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    }
+  ]
+}
diff --git a/content/ordering.ts b/content/ordering.ts
index c1aa6e5c274..a975a3b14c6 100644
--- a/content/ordering.ts
+++ b/content/ordering.ts
@@ -271,6 +271,7 @@ const MODULE_ORDERING: { [key in SectionID]: Chapter[] } = {
         'game-theory',
         'multiplicative',
         'matroid-isect',
+        'random',
         'interactive',
         'vectorization',
       ],


Reviews:
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:22:35Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:22:53Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:24:23Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T22:25:03Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T22:26:17Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:27:53Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T22:29:18Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:32:09Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:32:36Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T22:35:37Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:36:48Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:39:31Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T22:45:29Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:45:55Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T22:48:23Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T23:01:39Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T01:28:27Z
user: login: Sosuke23
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T01:31:11Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T01:33:04Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T01:34:20Z
user: login: Sosuke23
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T01:43:57Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T02:51:21Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T02:52:33Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T02:58:27Z
user: login: Sosuke23
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T17:35:15Z
user: login: Sosuke23
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T18:18:12Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:00:09Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:00:23Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:01:59Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T04:06:25Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:09:28Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T04:16:34Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T04:18:02Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:18:24Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:31:39Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:32:42Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T04:36:09Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:36:20Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:36:53Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:40:37Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T04:42:23Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T04:57:57Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T04:59:17Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T05:01:48Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:02:02Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:03:49Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:04:53Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:05:03Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T05:10:51Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T05:11:30Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:14:19Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:14:57Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:26:26Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:41:56Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T05:47:43Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T13:05:46Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T13:07:41Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T17:18:25Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T17:18:34Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T17:25:49Z
user: login: bqi343
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-10T22:18:53Z
user: login: RyanFu08
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T22:47:55Z
user: login: bqi343
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-10T23:55:47Z
user: login: eysbutno
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T01:38:26Z

Review comments:
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is quite difficult. However, we can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
path: content/6_Advanced/random.mdx
user: login: bqi343
body: > Calculating the exact probability that our approach works is quite difficult.

I don't understand, why isn't it just given by the summation you wrote above?
created_at: 2025-04-08T22:22:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
path: content/6_Advanced/random.mdx
user: login: bqi343
body: 999 or 99?
created_at: 2025-04-08T22:22:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: this seems like quite a high failure probability. considering that there are 10K queries and you used S<99?
created_at: 2025-04-08T22:24:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is quite difficult. However, we can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Oops - I was referring to the probability for AC the actual solution, not the coin flipping hypothetical
created_at: 2025-04-08T22:25:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Graph takes into account 10k queries, the .000309 stuff is also just to provide some basis for intuition on probability exponentially decreasing with increased trials.
created_at: 2025-04-08T22:26:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: ok I guess summing the minimum is better than summing coin tosses maybe?
created_at: 2025-04-08T22:27:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Should I just remove the coin toss example completely if it is too distracting?
created_at: 2025-04-08T22:29:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: > probability exponentially decreasing with increased trials.

it's not exponential is it? actually maybe it is
created_at: 2025-04-08T22:32:09Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: > Should I just remove the coin toss example completely if it is too distracting?

well, it's better than nothing but I feel like the intuition it gives is also sorta misleading
created_at: 2025-04-08T22:32:36Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: > ok I guess summing the minimum is better than summing coin tosses maybe?

I don't quite understand - could you elaborate a bit?
created_at: 2025-04-08T22:35:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: from the coin toss example you presented, it gives me the intuition that randomness is not sufficient to solve this problem reliably :/
created_at: 2025-04-08T22:36:48Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+#define all(x) begin(x), end(x)
+#define sz(x) (int)(x).size()
+
+const int mxn = 5e5 + 5;
+const int S = 75;
+const int inf = 2e8;
+
+unsigned int va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+int seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline int range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	int res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: why inline?
created_at: 2025-04-08T22:39:31Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+#define all(x) begin(x), end(x)
+#define sz(x) (int)(x).size()
+
+const int mxn = 5e5 + 5;
+const int S = 75;
+const int inf = 2e8;
+
+unsigned int va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+int seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline int range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	int res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: just a habit I have when I write template code... I can remove all of this if it's not up to usaco.guide standards
created_at: 2025-04-08T22:45:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: I am also confused by the graph. Why are you only using S=75 if it only lets you pass a test case with better than half probability?
created_at: 2025-04-08T22:45:55Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+#define all(x) begin(x), end(x)
+#define sz(x) (int)(x).size()
+
+const int mxn = 5e5 + 5;
+const int S = 75;
+const int inf = 2e8;
+
+unsigned int va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+int seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline int range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	int res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: can you remove it? it doesn't do anything here
created_at: 2025-04-08T22:48:22Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: > I am also confused by the graph. Why are you only using S=75 if it only lets you pass a test case with better than half probability?

To be completely transparent, I passed the problem before I calculated the probabilities of success, and was quite surprised by the results of the probability calculations. In fact, you can get AC on this problem even with S=28...

I've modified the code such that S=100 now (previously I was having some issues with memory so didn't push it that high).
created_at: 2025-04-08T23:01:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,81 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
path: content/6_Advanced/random.problems.json
user: login: Sosuke23
body: ```suggestion
        "kind": "in-module",
        "moduleId": "random"
```
created_at: 2025-04-09T01:24:27Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,81 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
path: content/6_Advanced/random.problems.json
user: login: Sosuke23
body: ```suggestion
        "kind": "in-module",
        "moduleId": "random"
```
created_at: 2025-04-09T01:25:12Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,81 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/contest/840/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site"
path: content/6_Advanced/random.problems.json
user: login: Sosuke23
body: ```suggestion
        "kind": "autogen-label-from-site",
        "site": "CF"
```
created_at: 2025-04-09T01:26:37Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,81 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/contest/840/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site"
path: content/6_Advanced/random.problems.json
user: login: Sosuke23
body: ```suggestion
        "kind": "autogen-label-from-site",
        "site": "CF"
```
created_at: 2025-04-09T01:26:51Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,81 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/contest/840/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site"
+      }
+    },
+    {
+      "uniqueId": "cf-442E",
+      "name": "Gena and Second Distance",
+      "url": "https://codeforces.com/contest/442/problem/E",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site"
path: content/6_Advanced/random.problems.json
user: login: Sosuke23
body: ```suggestion
        "kind": "autogen-label-from-site",
        "site": "CF"
```
created_at: 2025-04-09T01:27:06Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,81 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module"
path: content/6_Advanced/random.problems.json
user: login: bqi343
body: solutionMetadata needs to be formatted the same way as other in-module problems
created_at: 2025-04-09T01:28:27Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+inline int read() {
+	int num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (int)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+const int mxn = 5e5 + 5;
+const int S = 100;
+const us inf = 65535;
+
+us va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+us seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline us range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	us res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
+	memset(heavy, -1, sizeof(heavy));
+	dfs(0);
+	decompose(0, 0);
+}
+inline us path_min(int a, int b, int i) {
+	us res = inf;
+	for (; head[a] != head[b]; b = f[head[b]]) {
+		if (depth[head[a]] > depth[head[b]]) swap(a, b);
+		res = min(res, SGT::range_min(pos[head[b]], pos[b], i));
+	}
+	if (depth[a] > depth[b]) swap(a, b);
+	res = min(res, SGT::range_min(pos[a], pos[b], i));
+	return res;
+}
+}  // namespace HLD
+
+void solve() {
+	n = read();
+	m = read();
+	for (int i = 1; i <= n; i++)
+		for (int j = 0; j < S; j++) { va[i][j] = rand() % (inf + 1); }
+	for (int i = 0; i < n; i++) c[i] = read();
+	HLD::clear(n);
+	for (int i = 1; i < n; i++) {
+		int u = read() - 1, v = read() - 1;
+		HLD::add_edge(u, v);
+	}
+	HLD::init();
+	SGT::build();
+
+	int cnt = 0;
+	while (m--) {
+		int tp = read();
+		if (tp == 1) {
+			int x = read() ^ cnt, y = read() ^ cnt;
+			SGT::point_update(HLD::pos[x - 1], y);
+		} else {
+			int a = read() ^ cnt, b = read() ^ cnt, c = read() ^ cnt, d = read() ^ cnt;
+			--a;
+			--b;
+			--c;
+			--d;
+			long long c1 = 0, c2 = 0;
+			for (int i = 0; i < S; i++) {
+				c1 += HLD::path_min(a, b, i);
+				c2 += HLD::path_min(c, d, i);
+			}
+			if (c1 < c2) {
+				cnt++;
+				cout << "Yes\n";
+			} else {
+				cout << "No\n";
+			}
+		}
+	}
+}
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: remove 326,327
created_at: 2025-04-09T01:28:57Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: ```suggestion
#include <bits/stdc++.h>
```
created_at: 2025-04-09T01:30:02Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: make constants full captial 
created_at: 2025-04-09T01:30:22Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: remove 83,84
created_at: 2025-04-09T01:30:49Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
path: content/6_Advanced/random.mdx
user: login: bqi343
body: This is not a safe assumption - I remember seeing some CF problem with many hundreds of tests.
created_at: 2025-04-09T01:33:04Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
path: content/6_Advanced/random.mdx
user: login: bqi343
body: is cin not fast enough?
created_at: 2025-04-09T01:34:20Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+inline int read() {
+	int num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (int)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+const int mxn = 5e5 + 5;
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: here also constants in capital
created_at: 2025-04-09T01:37:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+inline int read() {
+	int num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (int)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+const int mxn = 5e5 + 5;
+const int S = 100;
+const us inf = 65535;
+
+us va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+us seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline us range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	us res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
+	memset(heavy, -1, sizeof(heavy));
+	dfs(0);
+	decompose(0, 0);
+}
+inline us path_min(int a, int b, int i) {
+	us res = inf;
+	for (; head[a] != head[b]; b = f[head[b]]) {
+		if (depth[head[a]] > depth[head[b]]) swap(a, b);
+		res = min(res, SGT::range_min(pos[head[b]], pos[b], i));
+	}
+	if (depth[a] > depth[b]) swap(a, b);
+	res = min(res, SGT::range_min(pos[a], pos[b], i));
+	return res;
+}
+}  // namespace HLD
+
+void solve() {
+	n = read();
+	m = read();
+	for (int i = 1; i <= n; i++)
+		for (int j = 0; j < S; j++) { va[i][j] = rand() % (inf + 1); }
+	for (int i = 0; i < n; i++) c[i] = read();
+	HLD::clear(n);
+	for (int i = 1; i < n; i++) {
+		int u = read() - 1, v = read() - 1;
+		HLD::add_edge(u, v);
+	}
+	HLD::init();
+	SGT::build();
+
+	int cnt = 0;
+	while (m--) {
+		int tp = read();
+		if (tp == 1) {
+			int x = read() ^ cnt, y = read() ^ cnt;
+			SGT::point_update(HLD::pos[x - 1], y);
+		} else {
+			int a = read() ^ cnt, b = read() ^ cnt, c = read() ^ cnt, d = read() ^ cnt;
+			--a;
+			--b;
+			--c;
+			--d;
+			long long c1 = 0, c2 = 0;
+			for (int i = 0; i < S; i++) {
+				c1 += HLD::path_min(a, b, i);
+				c2 += HLD::path_min(c, d, i);
+			}
+			if (c1 < c2) {
+				cnt++;
+				cout << "Yes\n";
+			} else {
+				cout << "No\n";
+			}
+		}
+	}
+}
+
+signed main() {
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: is there any issue with "int main()"?
created_at: 2025-04-09T01:38:18Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: I think it should be written like ":return The approximated........"

check it once with module
created_at: 2025-04-09T01:42:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: same for the params
created_at: 2025-04-09T01:43:50Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: >> probability exponentially decreasing with increased trials.

> it's not exponential is it? it's more like e^{-sqrt trials}

Well isn't e^{-sqrt x} "exponential" in the sense that the number of trials is in the exponent? Though, I'm not too good with terminology, would appreciate a better term for this?
created_at: 2025-04-09T02:51:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+inline int read() {
+	int num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (int)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+const int mxn = 5e5 + 5;
+const int S = 100;
+const us inf = 65535;
+
+us va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+us seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline us range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	us res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
+	memset(heavy, -1, sizeof(heavy));
+	dfs(0);
+	decompose(0, 0);
+}
+inline us path_min(int a, int b, int i) {
+	us res = inf;
+	for (; head[a] != head[b]; b = f[head[b]]) {
+		if (depth[head[a]] > depth[head[b]]) swap(a, b);
+		res = min(res, SGT::range_min(pos[head[b]], pos[b], i));
+	}
+	if (depth[a] > depth[b]) swap(a, b);
+	res = min(res, SGT::range_min(pos[a], pos[b], i));
+	return res;
+}
+}  // namespace HLD
+
+void solve() {
+	n = read();
+	m = read();
+	for (int i = 1; i <= n; i++)
+		for (int j = 0; j < S; j++) { va[i][j] = rand() % (inf + 1); }
+	for (int i = 0; i < n; i++) c[i] = read();
+	HLD::clear(n);
+	for (int i = 1; i < n; i++) {
+		int u = read() - 1, v = read() - 1;
+		HLD::add_edge(u, v);
+	}
+	HLD::init();
+	SGT::build();
+
+	int cnt = 0;
+	while (m--) {
+		int tp = read();
+		if (tp == 1) {
+			int x = read() ^ cnt, y = read() ^ cnt;
+			SGT::point_update(HLD::pos[x - 1], y);
+		} else {
+			int a = read() ^ cnt, b = read() ^ cnt, c = read() ^ cnt, d = read() ^ cnt;
+			--a;
+			--b;
+			--c;
+			--d;
+			long long c1 = 0, c2 = 0;
+			for (int i = 0; i < S; i++) {
+				c1 += HLD::path_min(a, b, i);
+				c2 += HLD::path_min(c, d, i);
+			}
+			if (c1 < c2) {
+				cnt++;
+				cout << "Yes\n";
+			} else {
+				cout << "No\n";
+			}
+		}
+	}
+}
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Necessary due to tight TL. See: https://qoj.ac/submission/970005
created_at: 2025-04-09T02:52:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Could you elaborate a bit? Not too sure what this means
created_at: 2025-04-09T02:58:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,341 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: I have updated it.... you can follow the same for future contents
created_at: 2025-04-09T17:35:15Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
path: content/6_Advanced/random.mdx
user: login: Sosuke23
body: ```suggestion
![Graph](./assets/random-graph.png)
```
created_at: 2025-04-09T18:18:12Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: actually it's more like e^{-(something propto x)} anyway so it's fine
created_at: 2025-04-10T04:00:09Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: bqi343
body: >  In fact, you can get AC on this problem even with S=28...

huh the test data must be terrible then ... 

I just tried setting S=28 in your sol and generating some trivial queries, and it fails a significant fraction of them.
created_at: 2025-04-10T04:00:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+#define all(x) begin(x), end(x)
+#define sz(x) (int)(x).size()
+
+const int mxn = 5e5 + 5;
+const int S = 75;
+const int inf = 2e8;
+
+unsigned int va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+int seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline int range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	int res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: same in the other places
created_at: 2025-04-10T04:01:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $999$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: S=28 submission: https://qoj.ac/submission/969131
created_at: 2025-04-10T04:06:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,86 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/problemset/problem/840/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-442E",
+      "name": "Gena and Second Distance",
+      "url": "https://codeforces.com/contest/442/problem/E",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "loj-2339",
+      "name": "Channel",
+      "url": "https://vjudge.net/problem/LibreOJ-2339#author=DeepSeek_en",
path: content/6_Advanced/random.problems.json
user: login: bqi343
body: how are you supposed to do this problem using randomness?
created_at: 2025-04-10T04:09:28Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,86 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/problemset/problem/840/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-442E",
+      "name": "Gena and Second Distance",
+      "url": "https://codeforces.com/contest/442/problem/E",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "loj-2339",
+      "name": "Channel",
+      "url": "https://vjudge.net/problem/LibreOJ-2339#author=DeepSeek_en",
path: content/6_Advanced/random.problems.json
user: login: RyanFu08
body: If I remember correctly, the rough idea of the randomized (unintended) solution is to randomly choose a starting point, DFS, and take the best value from that DFS as your new starting point, and you'll get the correct answer using some heuristics + randomization

My own code that does this is quite ugly, let me attempt to find a decent one however
created_at: 2025-04-10T04:16:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,86 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/problemset/problem/840/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-442E",
+      "name": "Gena and Second Distance",
+      "url": "https://codeforces.com/contest/442/problem/E",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "loj-2339",
+      "name": "Channel",
+      "url": "https://vjudge.net/problem/LibreOJ-2339#author=DeepSeek_en",
path: content/6_Advanced/random.problems.json
user: login: RyanFu08
body: See: https://loj.ac/s/1028787

I mainly included this problem because I felt it was a good example of how randomization could be used to create significantly easier unintended solutions
created_at: 2025-04-10T04:18:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,86 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "general": [
+    {
+      "uniqueId": "cf-840D",
+      "name": "Destiny",
+      "url": "https://codeforces.com/problemset/problem/840/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-444B",
+      "name": "DZY Loves FFT",
+      "url": "https://codeforces.com/problemset/problem/444/B",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "cf-442E",
+      "name": "Gena and Second Distance",
+      "url": "https://codeforces.com/contest/442/problem/E",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": false,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "autogen-label-from-site",
+        "site": "CF"
+      }
+    },
+    {
+      "uniqueId": "loj-2339",
+      "name": "Channel",
+      "url": "https://vjudge.net/problem/LibreOJ-2339#author=DeepSeek_en",
path: content/6_Advanced/random.problems.json
user: login: bqi343
body: well that doesn't sound legit at all, we shouldn't include this unless it's provable
created_at: 2025-04-10T04:18:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
path: content/6_Advanced/random.mdx
user: login: bqi343
body: wait, what about the time to factor?
created_at: 2025-04-10T04:31:38Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
path: content/6_Advanced/random.mdx
user: login: bqi343
body: can you clarify how the graph was constructed? Is it assuming only one test case of max size?
created_at: 2025-04-10T04:32:42Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Yes - I cheated a bit and looked at the test data, which only has one (non sample) testcase (presumably you could check testcase count in-contest as well? I've never actually participated in UCup so I'm not sure)
created_at: 2025-04-10T04:36:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: is this necessary?
created_at: 2025-04-10T04:36:20Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,74 @@
+{
+  "MODULE_ID": "random",
+  "ghd": [
+    {
+      "uniqueId": "cf-364D",
+      "name": "Ghd",
+      "url": "https://codeforces.com/contest/364/problem/D",
+      "source": "CF",
+      "difficulty": "Normal",
+      "isStarred": true,
+      "tags": ["Random"],
+      "solutionMetadata": {
+        "kind": "in-module",
+        "moduleId": "random"
+      }
+    }
+  ],
+  "coat2sb": [
+    {
+      "uniqueId": "qoj-1267",
+      "name": "Count on a Tree II Striking Back",
+      "url": "https://qoj.ac/contest/503/problem/1267",
+      "source": "QOJ",
+      "difficulty": "Normal",
path: content/6_Advanced/random.problems.json
user: login: bqi343
body: this should definitely be harder compared to the first example
created_at: 2025-04-10T04:36:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
path: content/6_Advanced/random.mdx
user: login: bqi343
body: idk. can you mention it in the module?
created_at: 2025-04-10T04:40:37Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Input volume is quite high, my code TLEs without the read function for S=100: https://qoj.ac/submission/971284
created_at: 2025-04-10T04:42:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: I also get TLE when submitting the in-module solution without any changes :/

https://qoj.ac/submission/971304
created_at: 2025-04-10T04:57:57Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Can I resolve this (not too sure about guidelines for problems requiring custom io ... should I switch this to the template provided in [faster io methods](https://usaco.guide/general/fast-io))

(oops didn't see the previous reply)
created_at: 2025-04-10T04:59:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: what if it's just variation in judging times though?
created_at: 2025-04-10T05:01:48Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Perhaps it was removing the inlines? My submission passes with S=150, even: https://qoj.ac/submission/969807
created_at: 2025-04-10T05:02:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: > what if it's just variation in judging times though?

Uhh given S=150 is literally running 1.5x the operations, I would assume not?
created_at: 2025-04-10T05:03:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Ok nvm, the exact code from my AC submissions are getting TLE now??
created_at: 2025-04-10T05:04:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Let me try to clear this up
created_at: 2025-04-10T05:05:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: https://github.com/cpinitiative/usaco-guide/pull/5277#discussion_r2036495805

sure if it helps
created_at: 2025-04-10T05:10:51Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: https://judge.yosupo.jp/submission/4542

might be more convenient to use
created_at: 2025-04-10T05:11:29Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Ok S=150 now passes in 1.6 seconds???

Was Qingyu playing Genshin Impact on the QOJ server or something 😭 
created_at: 2025-04-10T05:14:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: https://qoj.ac/submission/971327
created_at: 2025-04-10T05:14:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: > what if it's just variation in judging times though?

I've contacted one of the judge admins I know to ask if this is typical, will follow up on this tmrw hopefully
created_at: 2025-04-10T05:26:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: > fwd Qingyu: It was in the middle of a server upgrade yesterday, and the judgehosts was temporarily switched to a secondary server (which has some efficiency differences from the normal running server)

Anyway, he said that server should be consistent now? If this is indeed the case, this submission should suffice for the module: https://qoj.ac/submission/971360 ??
created_at: 2025-04-10T05:41:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Mainly, I optimized the point_update in the segtree to hopefully be a bit more cache friendly, and don't reinitialize all the random values. Theoretically, the point_update isn't called that much, and the extra rng() calls should only be O(1). I'm guessing it's the latter and rng() has bad constant...

Anyway, given that the judge behavior should be consistent now, the updated code should always AC comfortably.
created_at: 2025-04-10T05:47:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+#define all(x) begin(x), end(x)
+#define sz(x) (int)(x).size()
+
+const int mxn = 5e5 + 5;
+const int S = 75;
+const int inf = 2e8;
+
+unsigned int va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+int seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline int range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	int res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: (not resolved)
created_at: 2025-04-10T13:05:45Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
path: content/6_Advanced/random.mdx
user: login: bqi343
body: wait how do you know there is only one large test case, isn't T up to 4?
created_at: 2025-04-10T13:07:41Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,335 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 10$, and estimate the number of testcases in Codeforces to be $100$, our probability of success is $(\frac{1023}{1024})^{100} \approx .97$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+<Warning>
+
+Due to the high volume of input required for this problem, it may be useful (though not required) to use faster methods of input such as `scanf` or a custom input class to pass this problem.
+
+</Warning>
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 10;
+
+inline unsigned long long read() {
+	long long num = 0, sign = 1;
+	char ch = getchar();
+	while (ch < '0' || ch > '9') {
+		if (ch == '-') sign = -sign;
+		ch = getchar();
+	}
+	while (ch >= '0' && ch <= '9') {
+		num = num * 10 + (long long)ch - 48;
+		ch = getchar();
+	}
+	return num * sign;
+}
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+signed main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	n = read();
+	for (int i = 0; i < n; i++) a[i] = read();
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++)
+			cnt[lower_bound(dv, dv + ind, __gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random_graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	Parameters:
+	    k (int): The parameter defining the number of draws for each minimum:
+	             - The first group uses k draws.
+	             - The second group uses 2k draws.
+	    S (int): The number of independent trials (sums over S minima).
+
+	Returns:
+	    float: The approximated probability that the sum of the minima from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+#define all(x) begin(x), end(x)
+#define sz(x) (int)(x).size()
+
+const int mxn = 5e5 + 5;
+const int S = 75;
+const int inf = 2e8;
+
+unsigned int va[mxn][S];
+int n, m, c[mxn];
+
+namespace SGT {
+const int L = 1 << 19;
+int seg[2 * L][S];
+inline void build() {
+	for (int i = L - 1; i; i--)
+		for (int j = 0; j < S; j++) {
+			seg[i][j] = min(seg[2 * i][j], seg[2 * i + 1][j]);
+		}
+}
+inline void point_update(int i, int v) {
+	// 1 <= v <= n is the original color
+	for (int j = 0; j < S; j++) {
+		seg[L + i][j] = va[v][j];
+		for (int cv = (L + i) / 2; cv; cv /= 2)
+			seg[cv][j] = min(seg[2 * cv][j], seg[2 * cv + 1][j]);
+	}
+}
+inline int range_min(int l, int r, int j) {
+	// we can be sloppy since only 10k queries
+	int res = inf;
+	for (l += L, r += L + 1; l < r; l /= 2, r /= 2) {
+		if (l & 1) res = min(res, seg[l++][j]);
+		if (r & 1) res = min(res, seg[--r][j]);
+	}
+	return res;
+}
+}  // namespace SGT
+
+namespace HLD {
+const int mxn = 5e5 + 5;
+int f[mxn], depth[mxn], heavy[mxn], head[mxn], pos[mxn], cp = 0;
+vector<int> adj[mxn];
+inline void clear(int n) {
+	for (int i = 0; i < n; i++) adj[i].clear();
+	cp = 0;
+}
+inline void add_edge(int u, int v) {
+	adj[u].push_back(v);
+	adj[v].push_back(u);
+}
+int dfs(int v) {
+	int sz = 1, msz = 0;
+	for (int c : adj[v])
+		if (c != f[v]) {
+			f[c] = v, depth[c] = depth[v] + 1;
+			int csz = dfs(c);
+			sz += csz;
+			if (csz > msz) { msz = csz, heavy[v] = c; }
+		}
+	return sz;
+}
+void decompose(int v, int h) {
+	head[v] = h, pos[v] = cp++;
+	for (int i = 0; i < S; i++) SGT::seg[SGT::L + pos[v]][i] = va[c[v]][i];
+	if (heavy[v] != -1) decompose(heavy[v], h);
+	for (int c : adj[v]) {
+		if (c == f[v] || c == heavy[v]) continue;
+		decompose(c, c);
+	}
+}
+inline void init() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Oops, I kept adding them back when pasting my code from QOJ... fixed now
created_at: 2025-04-10T17:18:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Updated
created_at: 2025-04-10T17:18:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Can I resolve this? Current code ACs in 1.6/4 second TL, and the judge behavior as of rn should be consistent.
created_at: 2025-04-10T17:25:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: bqi343
body: how much time does read() save?
created_at: 2025-04-10T22:18:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,318 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 \right)$, with the log factor occuring due to gcd computation.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+const int mxn = 1e6 + 5;
+const int S = 15;
+
+mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
+unsigned long long n, a[mxn], dv[mxn], cnt[mxn], ans, x, ind, d;
+
+int main() {
+	ios::sync_with_stdio(false);
+	cin.tie(nullptr);
+	cin >> n;
+	for (int i = 0; i < n; i++) cin >> a[i];
+	for (int s = 0; s < S; s++) {
+		x = a[rng() % n], ind = 0;
+		for (d = 1; d * d <= x; d++)
+			if (x % d == 0) {
+				dv[ind++] = d;
+				if (d * d != x) dv[ind++] = x / d;
+			}
+		sort(dv, dv + ind);
+		fill(cnt, cnt + ind, 0);
+		for (int i = 0; i < n; i++) cnt[lower_bound(dv, dv + ind, gcd(a[i], x)) - dv]++;
+		for (int i = 0; i < ind; i++)
+			for (int j = 0; j < i; j++)
+				if (dv[i] % dv[j] == 0) cnt[j] += cnt[i];
+		for (int i = 0; i < ind; i++)
+			if (cnt[i] + cnt[i] >= n) ans = max(ans, dv[i]);
+	}
+	cout << ans;
+}
+```
+
+## Example - Count on a Tree II Striking Back
+
+<FocusProblem problem="coat2sb" />
+
+Trying to solve this problem directly - explicitly finding values for $f(a,b)$ and $f(c,d)$ - is quite difficult. Supporting online queries of range count distinct along with updates is quite difficult to achieve on an array in reasonable complexity, and the fact that this problem occurs on a tree, with relative large bound for $n \leq 500$ $000$ makes it clear that solving for the value of $f$ is not intended.
+
+Instead, we can attempt to use the property given in the statement that either $f(a,b) \geq 2f(c,d)$ or $f(c,d) \geq 2f(a,b)$. This inspires the following thought - if we map each color to a random number, the path minimum along the path with more distinct colors will *probably* be a smaller value.
+
+We attempt to formalize this approach, and push the probability to an acceptable bound. Notably, the probability of failure is too high when we do the aforementioned random process once. To remedy this, we proceed as follows:
+
+- First we fix $S$ to be the number of "simulations" that we run.
+- Next, for each possible color $1 \leq c \leq n$, we define $v_{cj}$ as an independent random value within $[0,1]$, for each $1 \leq j \leq S$.
+- Then, we construct $S$ trees $T_i$, of the same structure as the initial tree, but with $v_{c_u i}$ marked on a node $u$.
+- For each query comparing $a,b,c,d$, we output $\texttt{Yes}$ if
+$$
+\sum_{i\leq S} \text{PathMin}(T_i,a,b) < \sum_{i\leq S} \text{PathMin}(T_i,c,d)
+$$
+and $\texttt{No}$ otherwise.
+
+This approach should "combine" the probabilities in a way that makes the more likely event (the path with more distinct values achieving a smaller value) exponentially more likely. For some intuition on this, if we flip a coin weighted with $\frac{2}{3}$ probability to be heads once, there is a $\frac{1}{3}$ probability it comes up tails more than heads. However, if we flip it $99$ times, the probability it comes up more tails more than heads becomes
+
+$$
+\sum_{k=50}^{99} \binom{99}{k} \left(\frac{1}{3}\right)^k \left(\frac{2}{3}\right)^{99-k} \approx .000309
+$$
+
+Calculating the exact probability that our approach works is more difficult than the coin toss example, but follows the same principle of failure becoming exponentially more unlikely across several trials. We can use some assumptions (notably the central limit theorem) to calculate a rough approximation of the probability of success. Here is a graph of the probability of passing the problem given a certain value of $S$. Note that the probability of success remains is largely the same across different counts of distinct colors along the path.
+
+![Graph](./assets/random-graph.png)
+
+The python code used to generate the estimates is shown below:
+
+```py
+import math
+from scipy.stats import norm
+
+
+def clt_probability(k, S):
+	"""
+	Computes the probability that the sum of S minima from 2k random draws
+	is less than the sum of S minima from k random draws, as approximated by the CLT.
+
+	The CLT approximation is given by:
+
+	   P(B<A) ≈ Φ(  (sqrt(S) * [k/((k+1)(2k+1)]) ) / sqrt( k/((k+1)^2(k+2)) + 2k/((2k+1)^2(2k+2)) ) )
+
+	:param k: The number of draws for each minimum:
+			- The first group uses k draws.
+	            	- The second group uses 2k draws.
+	:param S: The number of independent trials (sums over S minima).
+	:return: The approximated probability that the sum of the minima
+		 from 2k draws is less than that from k draws.
+	"""
+	numerator = math.sqrt(S) * k / ((k + 1) * (2 * k + 1))
+
+	var_X = k / (((k + 1) ** 2) * (k + 2))
+	var_Y = 2 * k / (((2 * k + 1) ** 2) * (2 * k + 2))
+
+	denominator = math.sqrt(var_X + var_Y)
+
+	z_score = numerator / denominator
+
+	probability = norm.cdf(z_score)
+
+	return probability
+```
+
+### Implementation
+
+By supporting path queries with HLD, we can solve this problem in $\mathcal{O}(S\cdot(n + m\log^2n))$.
+
+```cpp
+#include "bits/stdc++.h"
+using namespace std;
+
+using us = unsigned short;
+
+int read() {
path: content/6_Advanced/random.mdx
user: login: RyanFu08
body: Now, only .4 seconds. I've removed it from the module code.
created_at: 2025-04-10T22:47:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,337 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
+frequency: 0
+---
+
+<Resources>
+	<Resource
+		source="CF"
+		title="Randomized algorithms lecture, part 1 & 2"
+		url="https://codeforces.com/blog/entry/71097"
+	>
+	</Resource>
+	<Resource
+		source="CF"
+		title="Randomized Algorithms and Online Judges"
+		url="https://codeforces.com/blog/entry/84215"
+	>
+	</Resource>
+	<Resource
+		source="Petr"
+		title="Random problems"
+		url="https://blog.mitrichev.ch/2016/07/random-problems.html"
+	>
+	</Resource>
+
+</Resources>
+
+Sometimes, we can use randomized algorithms to solve tasks quite difficult for deterministic algorithms.
+
+## Example - Ghd
+
+<FocusProblem problem="ghd" />
+
+Let the answer be $k$. The key observation for this problem is that a randomly selected integer in $a$ has at least a $\frac{1}{2}$ chance to be divisible by $k$.
+
+Thus, we can repeat the following procedure $S$ times to find the optimal answer with probability $1-\frac{1}{2^S}$:
+
+- Let $x$ be a randomly selected value in $a$.
+- For each divisor $d \mid x$, determine how many numbers $d$ divides into in $a$.
+- Take our answer to be the minimum of all $d$ such that $\geq \frac{n}{2}$ numbers in $a$ are divisible by $d$
+
+If we take $S = 15$, and estimate the number of testcases in Codeforces to be $500$, our probability of success is $(1-\frac{1}{2^{15}})^{500} \approx .984$, which is acceptable.
+
+### Implementation
+
+Our approach has a time complexity of $\mathcal{O}\left(S\cdot n\log a + S \cdot d(a)^2 + S\cdot \sqrt{a}\right)$, with the log factor occuring due to gcd computation, and the sqrt due to factoring.
path: content/6_Advanced/random.mdx
user: login: eysbutno
body: ```suggestion
Our approach has a time complexity of $\mathcal{O}\left(S \cdot \left(N\log A + d(A)^2 + \sqrt{A}\right)\right)$
, with the log factor occurring due to GCD computation, and the sqrt due to factoring.
```
created_at: 2025-04-11T01:13:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,337 @@
+---
+id: random
+title: Randomness
+author: Ryan Fu
+prerequisites:
+description: Using randomized algorithms to solve problems
path: content/6_Advanced/random.mdx
user: login: eysbutno
body: ```suggestion
description: Using randomized algorithms to solve problems.
```
created_at: 2025-04-11T01:18:02Z
author_association: CONTRIBUTOR

PR comments:
user: login: bqi343
created_at: 2025-04-10T04:26:56Z
body: here is an easy problem maybe worth including: https://www.facebook.com/codingcompetitions/hacker-cup/2024/practice-round/problems/C
author_association: MEMBER
user: login: RyanFu08
created_at: 2025-04-10T04:34:13Z
body: > here is an easy problem maybe worth including: https://www.facebook.com/codingcompetitions/hacker-cup/2024/practice-round/problems/C

Do you think it'd be worthwhile to include it in the module itself, or just in the problems? This seems similar to the Ghd problem, so if included in the module I would probably swap it out.
author_association: CONTRIBUTOR
user: login: bqi343
created_at: 2025-04-10T04:34:26Z
body: in the problems
author_association: MEMBER