From e0423866300adfe83f60663248fa52674e5c335c Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Mon, 17 Nov 2025 16:00:40 +0800 Subject: [PATCH 1/9] modify code --- src/class183/Code04_Tree1.java | 6 ++++-- src/class183/Code04_Tree2.java | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/class183/Code04_Tree1.java b/src/class183/Code04_Tree1.java index e2e16301..781ee6cb 100644 --- a/src/class183/Code04_Tree1.java +++ b/src/class183/Code04_Tree1.java @@ -82,6 +82,9 @@ public static void dfs(int u, int fa, int dis) { } } + // 从真正的头来到u时,路径权值和为dis + // 子树u上的点对(x, y),需要走过,x -> 真正的头 -> y + // 返回距离<=k的点对数量 public static long calc(int u, int dis) { cnta = 0; dfs(u, 0, dis); @@ -99,9 +102,8 @@ public static long calc(int u, int dis) { } public static long solve(int u) { - long ans = 0; - ans += calc(u, 0); vis[u] = true; + long ans = calc(u, 0); for (int e = head[u]; e > 0; e = nxt[e]) { int v = to[e]; if (!vis[v]) { diff --git a/src/class183/Code04_Tree2.java b/src/class183/Code04_Tree2.java index 9ed2a307..699cc5fa 100644 --- a/src/class183/Code04_Tree2.java +++ b/src/class183/Code04_Tree2.java @@ -96,9 +96,8 @@ //} // //long long solve(int u) { -// long long ans = 0; -// ans += calc(u, 0); // vis[u] = true; +// long long ans = calc(u, 0); // for (int e = head[u]; e; e = nxt[e]) { // int v = to[e]; // if (!vis[v]) { From 647825d23a401b7aacf04de991ac5914f7d9145f Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Mon, 17 Nov 2025 16:10:10 +0800 Subject: [PATCH 2/9] modify code --- src/class183/Code04_Tree1.java | 1 + src/class183/Code04_Tree2.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/class183/Code04_Tree1.java b/src/class183/Code04_Tree1.java index 781ee6cb..c8583ee1 100644 --- a/src/class183/Code04_Tree1.java +++ b/src/class183/Code04_Tree1.java @@ -3,6 +3,7 @@ // 距离<=k的点对数量,java版 // 一共有n个节点,给定n-1条边,每条边有边权,所有节点组成一棵树 // 给定数字k,求出树上两点距离<=k的点对数量 +// 本题规定(x, x)不是点对,(x, y)和(y, x)认为是同一个点对 // 1 <= n <= 4 * 10^4 // 0 <= 边权 <= 10^3 // 0 <= k <= 2 * 10^4 diff --git a/src/class183/Code04_Tree2.java b/src/class183/Code04_Tree2.java index 699cc5fa..540bb372 100644 --- a/src/class183/Code04_Tree2.java +++ b/src/class183/Code04_Tree2.java @@ -3,6 +3,7 @@ // 距离<=k的点对数量,C++版 // 一共有n个节点,给定n-1条边,每条边有边权,所有节点组成一棵树 // 给定数字k,求出树上两点距离<=k的点对数量 +// 本题规定(x, x)不是点对,(x, y)和(y, x)认为是同一个点对 // 1 <= n <= 4 * 10^4 // 0 <= 边权 <= 10^3 // 0 <= k <= 2 * 10^4 From 5137a5c40af75bdf28ac910d9a3581159acc3578 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Mon, 17 Nov 2025 17:33:40 +0800 Subject: [PATCH 3/9] modify code --- src/class183/Code05_CloseVertices1.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/class183/Code05_CloseVertices1.java b/src/class183/Code05_CloseVertices1.java index bd753faf..8a0d82ee 100644 --- a/src/class183/Code05_CloseVertices1.java +++ b/src/class183/Code05_CloseVertices1.java @@ -125,6 +125,9 @@ public static void dfs(int u, int fa, int dis, int dep) { } } + // 从真正的头来到u时,路径权值和为dis,深度为dep + // 子树u上的点对(x, y),需要走过,x -> 真正的头 -> y + // 返回 距离<=limitw、边数<=limitwl 的点对数量 public static long calc(int u, int dis, int dep) { cnta = 0; dfs(u, 0, dis, dep); From 277fb42afc926cc5ebbfd78c87ecb2bf09a5af32 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Tue, 18 Nov 2025 13:29:44 +0800 Subject: [PATCH 4/9] modify code --- src/class183/Code05_CloseVertices1.java | 46 ++++++++++++++----------- src/class183/Code05_CloseVertices2.java | 38 ++++++++++---------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/class183/Code05_CloseVertices1.java b/src/class183/Code05_CloseVertices1.java index 8a0d82ee..05ff0f05 100644 --- a/src/class183/Code05_CloseVertices1.java +++ b/src/class183/Code05_CloseVertices1.java @@ -3,12 +3,10 @@ // 相近点对的数量,java版 // 一共有n个节点,所有节点组成一棵树,1号节点是树头 // 从2号点开始,给定每个点的父节点编号、与父节点之间无向边的边权 -// 给定两个整数limitl、limitw,如下为(a, b)是相近点对的定义 -// 首先a < b,其次两者简单路径的边数不超过limitl、权值和不超过limitw -// 打印树上有多少相近点对 -// 1 <= limitl <= n <= 10^5 -// 0 <= limitw <= 10^9 -// 0 <= 边权 <= 10^4 +// 给定两个整数limitl、limitw,要求两点之间的简单路径满足如下关系 +// 路径权值和 <= limitw、路径边数 <= limitl,求出这样的点对数量 +// 本题规定(x, x)不是点对,(x, y)和(y, x)认为是同一个点对 +// 1 <= limitl <= n <= 10^5 0 <= limitw <= 10^9 0 <= 边权 <= 10^4 // 测试链接 : https://www.luogu.com.cn/problem/CF293E // 测试链接 : https://codeforces.com/problemset/problem/293/E // 提交以下的code,提交时请把类名改成"Main",可以通过所有测试用例 @@ -33,7 +31,7 @@ public class Code05_CloseVertices1 { public static int[] siz = new int[MAXN]; public static int[] disArr = new int[MAXN]; - public static int[] depArr = new int[MAXN]; + public static int[] edgeArr = new int[MAXN]; public static int cnta; public static int[] tree = new int[MAXN]; @@ -46,7 +44,7 @@ public static void sort(int l, int r) { while (disArr[j] > pivot) j--; if (i <= j) { tmp = disArr[i]; disArr[i] = disArr[j]; disArr[j] = tmp; - tmp = depArr[i]; depArr[i] = depArr[j]; depArr[j] = tmp; + tmp = edgeArr[i]; edgeArr[i] = edgeArr[j]; edgeArr[j] = tmp; i++; j--; } } @@ -66,6 +64,9 @@ public static int lowbit(int i) { } public static void add(int i, int v) { + // 边的数量最小是0,但是树状数组下标从1开始 + // 所以i++,平移一下,然后使用树状数组 + i++; while (i <= limitl + 1) { tree[i] += v; i += lowbit(i); @@ -73,6 +74,9 @@ public static void add(int i, int v) { } public static int sum(int i) { + // 边的数量最小是0,但是树状数组下标从1开始 + // 所以i++,平移一下,然后使用树状数组 + i++; int ret = 0; while (i > 0) { ret += tree[i]; @@ -111,38 +115,38 @@ public static int getCentroid(int u, int fa) { return u; } - public static void dfs(int u, int fa, int dis, int dep) { - if (dis > limitw || dep > limitl + 1) { + public static void dfs(int u, int fa, int dis, int edge) { + if (dis > limitw || edge > limitl) { return; } disArr[++cnta] = dis; - depArr[cnta] = dep; + edgeArr[cnta] = edge; for (int e = head[u]; e > 0; e = nxt[e]) { int v = to[e]; if (v != fa && !vis[v]) { - dfs(v, u, dis + weight[e], dep + 1); + dfs(v, u, dis + weight[e], edge + 1); } } } - // 从真正的头来到u时,路径权值和为dis,深度为dep + // 从真正的头来到u时,路径权值和为dis,边的数量为edge // 子树u上的点对(x, y),需要走过,x -> 真正的头 -> y // 返回 距离<=limitw、边数<=limitwl 的点对数量 - public static long calc(int u, int dis, int dep) { + public static long calc(int u, int dis, int edge) { cnta = 0; - dfs(u, 0, dis, dep); + dfs(u, 0, dis, edge); sort(1, cnta); for (int i = 1; i <= cnta; i++) { - add(depArr[i], 1); + add(edgeArr[i], 1); } long ret = 0; for (int l = 1, r = cnta; l <= r;) { if (disArr[l] + disArr[r] <= limitw) { - add(depArr[l], -1); - ret += sum(limitl - depArr[l] + 2); + add(edgeArr[l], -1); + ret += sum(limitl - edgeArr[l]); l++; } else { - add(depArr[r], -1); + add(edgeArr[r], -1); r--; } } @@ -151,11 +155,11 @@ public static long calc(int u, int dis, int dep) { public static long solve(int u) { vis[u] = true; - long ans = calc(u, 0, 1); + long ans = calc(u, 0, 0); for (int e = head[u]; e > 0; e = nxt[e]) { int v = to[e]; if (!vis[v]) { - ans -= calc(v, weight[e], 2); + ans -= calc(v, weight[e], 1); ans += solve(getCentroid(v, u)); } } diff --git a/src/class183/Code05_CloseVertices2.java b/src/class183/Code05_CloseVertices2.java index 3331a872..92c5547e 100644 --- a/src/class183/Code05_CloseVertices2.java +++ b/src/class183/Code05_CloseVertices2.java @@ -3,12 +3,10 @@ // 相近点对的数量,C++版 // 一共有n个节点,所有节点组成一棵树,1号节点是树头 // 从2号点开始,给定每个点的父节点编号、与父节点之间无向边的边权 -// 给定两个整数limitl、limitw,如下为(a, b)是相近点对的定义 -// 首先a < b,其次两者简单路径的边数不超过limitl、权值和不超过limitw -// 打印树上有多少相近点对 -// 1 <= limitl <= n <= 10^5 -// 0 <= limitw <= 10^9 -// 0 <= 边权 <= 10^4 +// 给定两个整数limitl、limitw,要求两点之间的简单路径满足如下关系 +// 路径权值和 <= limitw、路径边数 <= limitl,求出这样的点对数量 +// 本题规定(x, x)不是点对,(x, y)和(y, x)认为是同一个点对 +// 1 <= limitl <= n <= 10^5 0 <= limitw <= 10^9 0 <= 边权 <= 10^4 // 测试链接 : https://www.luogu.com.cn/problem/CF293E // 测试链接 : https://codeforces.com/problemset/problem/293/E // 如下实现是C++的版本,C++版本和java版本逻辑完全一样 @@ -19,7 +17,7 @@ //using namespace std; // //struct Node { -// int dis, dep; +// int dis, edge; //}; // //bool NodeCmp(Node a, Node b) { @@ -55,6 +53,7 @@ //} // //void add(int i, int v) { +// i++; // while (i <= limitl + 1) { // tree[i] += v; // i += lowbit(i); @@ -62,6 +61,7 @@ //} // //int sum(int i) { +// i++; // int ret = 0; // while (i > 0) { // ret += tree[i]; @@ -100,34 +100,34 @@ // return u; //} // -//void dfs(int u, int fa, int dis, int dep) { -// if (dis > limitw || dep > limitl + 1) { +//void dfs(int u, int fa, int dis, int edge) { +// if (dis > limitw || edge > limitl) { // return; // } -// arr[++cnta] = { dis, dep }; +// arr[++cnta] = { dis, edge }; // for (int e = head[u]; e; e = nxt[e]) { // int v = to[e]; // if (v != fa && !vis[v]) { -// dfs(v, u, dis + weight[e], dep + 1); +// dfs(v, u, dis + weight[e], edge + 1); // } // } //} // -//long long calc(int u, int dis, int dep) { +//long long calc(int u, int dis, int edge) { // cnta = 0; -// dfs(u, 0, dis, dep); +// dfs(u, 0, dis, edge); // sort(arr + 1, arr + cnta + 1, NodeCmp); // for (int i = 1; i <= cnta; i++) { -// add(arr[i].dep, 1); +// add(arr[i].edge, 1); // } // long long ret = 0; // for (int l = 1, r = cnta; l <= r; ) { // if (arr[l].dis + arr[r].dis <= limitw) { -// add(arr[l].dep, -1); -// ret += sum(limitl - arr[l].dep + 2); +// add(arr[l].edge, -1); +// ret += sum(limitl - arr[l].edge); // l++; // } else { -// add(arr[r].dep, -1); +// add(arr[r].edge, -1); // r--; // } // } @@ -136,11 +136,11 @@ // //long long solve(int u) { // vis[u] = true; -// long long ans = calc(u, 0, 1); +// long long ans = calc(u, 0, 0); // for (int e = head[u]; e; e = nxt[e]) { // int v = to[e]; // if (!vis[v]) { -// ans -= calc(v, weight[e], 2); +// ans -= calc(v, weight[e], 1); // ans += solve(getCentroid(v, u)); // } // } From 4c3cfcf0f322ffad821e4675789f0373d09d76d3 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Tue, 18 Nov 2025 13:33:29 +0800 Subject: [PATCH 5/9] modify code --- src/class183/Code05_CloseVertices1.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/class183/Code05_CloseVertices1.java b/src/class183/Code05_CloseVertices1.java index 05ff0f05..dd5f3e67 100644 --- a/src/class183/Code05_CloseVertices1.java +++ b/src/class183/Code05_CloseVertices1.java @@ -63,9 +63,9 @@ public static int lowbit(int i) { return i & -i; } + // 边的数量从0开始,但是树状数组下标从1开始 + // 所以i++,平移一下,然后使用树状数组 public static void add(int i, int v) { - // 边的数量最小是0,但是树状数组下标从1开始 - // 所以i++,平移一下,然后使用树状数组 i++; while (i <= limitl + 1) { tree[i] += v; @@ -73,9 +73,9 @@ public static void add(int i, int v) { } } + // 边的数量从0开始,但是树状数组下标从1开始 + // 所以i++,平移一下,然后使用树状数组 public static int sum(int i) { - // 边的数量最小是0,但是树状数组下标从1开始 - // 所以i++,平移一下,然后使用树状数组 i++; int ret = 0; while (i > 0) { @@ -131,7 +131,7 @@ public static void dfs(int u, int fa, int dis, int edge) { // 从真正的头来到u时,路径权值和为dis,边的数量为edge // 子树u上的点对(x, y),需要走过,x -> 真正的头 -> y - // 返回 距离<=limitw、边数<=limitwl 的点对数量 + // 返回 路径权值和<=limitw、路径边数<=limitwl 的点对数量 public static long calc(int u, int dis, int edge) { cnta = 0; dfs(u, 0, dis, edge); From 736346e3c27e8f8772b1b2aef694209898b35aec Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Tue, 18 Nov 2025 13:43:38 +0800 Subject: [PATCH 6/9] modify code --- src/class183/Code06_Maschera1.java | 4 ++-- src/class183/Code06_Maschera2.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class183/Code06_Maschera1.java b/src/class183/Code06_Maschera1.java index 314f0b74..68ad3b1f 100644 --- a/src/class183/Code06_Maschera1.java +++ b/src/class183/Code06_Maschera1.java @@ -2,10 +2,10 @@ // 所有合法路径的魔力和,java版 // 一共有n个节点,给定n-1条边,每条边有边权,所有节点组成一棵树 -// 给定两个整数l、r,对于任意两个不同节点u、v,考虑它们之间的简单路径 +// 给定两个整数l、r,对于点对(x, y),考虑两点之间的简单路径 // 如果路径上边的数量在[l, r]范围内,则这条路径是合法路径 // 路径的魔力值 = 路径上所有边权的最大值,打印所有合法路径的魔力和 -// 注意,u到v和v到u视为两条不同的路径,均要计入答案 +// 本题规定(x, x)不是点对,(x, y)和(y, x)认为是不同的点对 // 1 <= n、边权 <= 10^5 // 测试链接 : https://www.luogu.com.cn/problem/P5351 // 提交以下的code,提交时请把类名改成"Main",可以通过所有测试用例 diff --git a/src/class183/Code06_Maschera2.java b/src/class183/Code06_Maschera2.java index d5b3106d..7e236ceb 100644 --- a/src/class183/Code06_Maschera2.java +++ b/src/class183/Code06_Maschera2.java @@ -2,10 +2,10 @@ // 所有合法路径的魔力和,C++版 // 一共有n个节点,给定n-1条边,每条边有边权,所有节点组成一棵树 -// 给定两个整数l、r,对于任意两个不同节点u、v,考虑它们之间的简单路径 +// 给定两个整数l、r,对于点对(x, y),考虑两点之间的简单路径 // 如果路径上边的数量在[l, r]范围内,则这条路径是合法路径 // 路径的魔力值 = 路径上所有边权的最大值,打印所有合法路径的魔力和 -// 注意,u到v和v到u视为两条不同的路径,均要计入答案 +// 本题规定(x, x)不是点对,(x, y)和(y, x)认为是不同的点对 // 1 <= n、边权 <= 10^5 // 测试链接 : https://www.luogu.com.cn/problem/P5351 // 如下实现是C++的版本,C++版本和java版本逻辑完全一样 From 39f7572bb4a067cb8c5a59eac566bb68b1f2a4c7 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Tue, 18 Nov 2025 13:57:29 +0800 Subject: [PATCH 7/9] modify code --- src/class183/Code05_CloseVertices1.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/class183/Code05_CloseVertices1.java b/src/class183/Code05_CloseVertices1.java index dd5f3e67..c2818685 100644 --- a/src/class183/Code05_CloseVertices1.java +++ b/src/class183/Code05_CloseVertices1.java @@ -34,6 +34,10 @@ public class Code05_CloseVertices1 { public static int[] edgeArr = new int[MAXN]; public static int cnta; + // 树状数组 + // 下标是边数,统计节点个数 + // 但是注意,边数从0开始,而树状数组的下标从1开始 + // 所以每次的入参i,需要i++进行平移 public static int[] tree = new int[MAXN]; public static void sort(int l, int r) { @@ -63,20 +67,16 @@ public static int lowbit(int i) { return i & -i; } - // 边的数量从0开始,但是树状数组下标从1开始 - // 所以i++,平移一下,然后使用树状数组 public static void add(int i, int v) { - i++; + i++; // 平移 while (i <= limitl + 1) { tree[i] += v; i += lowbit(i); } } - // 边的数量从0开始,但是树状数组下标从1开始 - // 所以i++,平移一下,然后使用树状数组 public static int sum(int i) { - i++; + i++; // 平移 int ret = 0; while (i > 0) { ret += tree[i]; From 7a5db7ddd8adf6706fb43e50cce55d30d5921c2b Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Tue, 18 Nov 2025 14:55:09 +0800 Subject: [PATCH 8/9] modify code --- src/class183/Code05_CloseVertices1.java | 6 +- src/class183/Code05_CloseVertices2.java | 6 +- src/class183/Code06_Maschera1.java | 79 +++++++++---------------- src/class183/Code06_Maschera2.java | 51 +++++----------- 4 files changed, 49 insertions(+), 93 deletions(-) diff --git a/src/class183/Code05_CloseVertices1.java b/src/class183/Code05_CloseVertices1.java index c2818685..7d956373 100644 --- a/src/class183/Code05_CloseVertices1.java +++ b/src/class183/Code05_CloseVertices1.java @@ -139,18 +139,18 @@ public static long calc(int u, int dis, int edge) { for (int i = 1; i <= cnta; i++) { add(edgeArr[i], 1); } - long ret = 0; + long ans = 0; for (int l = 1, r = cnta; l <= r;) { if (disArr[l] + disArr[r] <= limitw) { add(edgeArr[l], -1); - ret += sum(limitl - edgeArr[l]); + ans += sum(limitl - edgeArr[l]); l++; } else { add(edgeArr[r], -1); r--; } } - return ret; + return ans; } public static long solve(int u) { diff --git a/src/class183/Code05_CloseVertices2.java b/src/class183/Code05_CloseVertices2.java index 92c5547e..6019e1ac 100644 --- a/src/class183/Code05_CloseVertices2.java +++ b/src/class183/Code05_CloseVertices2.java @@ -120,18 +120,18 @@ // for (int i = 1; i <= cnta; i++) { // add(arr[i].edge, 1); // } -// long long ret = 0; +// long long ans = 0; // for (int l = 1, r = cnta; l <= r; ) { // if (arr[l].dis + arr[r].dis <= limitw) { // add(arr[l].edge, -1); -// ret += sum(limitl - arr[l].edge); +// ans += sum(limitl - arr[l].edge); // l++; // } else { // add(arr[r].edge, -1); // r--; // } // } -// return ret; +// return ans; //} // //long long solve(int u) { diff --git a/src/class183/Code06_Maschera1.java b/src/class183/Code06_Maschera1.java index 68ad3b1f..9ff7ee3e 100644 --- a/src/class183/Code06_Maschera1.java +++ b/src/class183/Code06_Maschera1.java @@ -17,7 +17,7 @@ public class Code06_Maschera1 { - public static int MAXN = 100001; + public static int MAXN = 100002; public static int n, l, r; public static int[] head = new int[MAXN]; @@ -29,11 +29,8 @@ public class Code06_Maschera1 { public static boolean[] vis = new boolean[MAXN]; public static int[] siz = new int[MAXN]; - public static int[] curMaxv = new int[MAXN]; - public static int[] curEdge = new int[MAXN]; - public static int cntc; - public static int[] allMaxv = new int[MAXN]; - public static int[] allEdge = new int[MAXN]; + public static int[] maxvArr = new int[MAXN]; + public static int[] edgeArr = new int[MAXN]; public static int cnta; public static int[] tree = new int[MAXN]; @@ -61,20 +58,20 @@ public static void pop() { e = stack[stacksize][4]; } - public static void sort(int[] maxv, int[] edge, int l, int r) { + public static void sort(int l, int r) { if (l >= r) return; - int i = l, j = r, pivot = maxv[(l + r) >> 1], tmp; + int i = l, j = r, pivot = maxvArr[(l + r) >> 1], tmp; while (i <= j) { - while (maxv[i] < pivot) i++; - while (maxv[j] > pivot) j--; + while (maxvArr[i] < pivot) i++; + while (maxvArr[j] > pivot) j--; if (i <= j) { - tmp = maxv[i]; maxv[i] = maxv[j]; maxv[j] = tmp; - tmp = edge[i]; edge[i] = edge[j]; edge[j] = tmp; + tmp = maxvArr[i]; maxvArr[i] = maxvArr[j]; maxvArr[j] = tmp; + tmp = edgeArr[i]; edgeArr[i] = edgeArr[j]; edgeArr[j] = tmp; i++; j--; } } - sort(maxv, edge, l, j); - sort(maxv, edge, i, r); + sort(l, j); + sort(i, r); } public static void addEdge(int u, int v, int w) { @@ -89,13 +86,15 @@ public static int lowbit(int i) { } public static void add(int i, int v) { - while (i <= r) { + i++; + while (i <= r + 1) { tree[i] += v; i += lowbit(i); } } public static int sum(int i) { + i++; int ret = 0; while (i > 0) { ret += tree[i]; @@ -170,8 +169,8 @@ public static void dfs1(int u, int fa, int maxv, int edge) { if (edge > r) { return; } - curMaxv[++cntc] = maxv; - curEdge[cntc] = edge; + maxvArr[++cnta] = maxv; + edgeArr[cnta] = edge; for (int e = head[u]; e > 0; e = nxt[e]) { int v = to[e]; if (v != fa && !vis[v]) { @@ -190,8 +189,8 @@ public static void dfs2(int cur, int fa, int pmaxv, int pedge) { if (edge > r) { continue; } - curMaxv[++cntc] = maxv; - curEdge[cntc] = edge; + maxvArr[++cnta] = maxv; + edgeArr[cnta] = edge; e = head[u]; } else { e = nxt[e]; @@ -206,51 +205,29 @@ public static void dfs2(int cur, int fa, int pmaxv, int pedge) { } } - public static long calc(int u) { - long ans = 0; + public static long calc(int u, int maxv, int edge) { cnta = 0; - for (int e = head[u]; e > 0; e = nxt[e]) { - int v = to[e]; - if (!vis[v]) { - cntc = 0; - // dfs1(v, u, weight[e], 1); - dfs2(v, u, weight[e], 1); - sort(curMaxv, curEdge, 1, cntc); - for (int i = 1; i <= cntc; i++) { - ans -= 1L * curMaxv[i] * (sum(r - curEdge[i]) - sum(l - curEdge[i] - 1)); - add(curEdge[i], 1); - } - for (int i = 1; i <= cntc; i++) { - add(curEdge[i], -1); - } - for (int i = 1; i <= cntc; i++) { - allMaxv[++cnta] = curMaxv[i]; - allEdge[cnta] = curEdge[i]; - } - } - } - sort(allMaxv, allEdge, 1, cnta); - for (int i = 1; i <= cnta; i++) { - ans += 1L * allMaxv[i] * (sum(r - allEdge[i]) - sum(l - allEdge[i] - 1)); - add(allEdge[i], 1); - } + // dfs1(u, 0, maxv, edge); + dfs2(u, 0, maxv, edge); + sort(1, cnta); + long ans = 0; for (int i = 1; i <= cnta; i++) { - add(allEdge[i], -1); + ans += 1L * maxvArr[i] * (sum(r - edgeArr[i]) - sum(l - edgeArr[i] - 1)); + add(edgeArr[i], 1); } for (int i = 1; i <= cnta; i++) { - if (allEdge[i] >= l) { - ans += allMaxv[i]; - } + add(edgeArr[i], -1); } return ans; } public static long solve(int u) { vis[u] = true; - long ans = calc(u); + long ans = calc(u, 0, 0); for (int e = head[u]; e > 0; e = nxt[e]) { int v = to[e]; if (!vis[v]) { + ans -= calc(v, weight[e], 1); ans += solve(getCentroid(v, u)); } } diff --git a/src/class183/Code06_Maschera2.java b/src/class183/Code06_Maschera2.java index 7e236ceb..db926111 100644 --- a/src/class183/Code06_Maschera2.java +++ b/src/class183/Code06_Maschera2.java @@ -23,7 +23,7 @@ // return a.maxv < b.maxv; //} // -//const int MAXN = 100001; +//const int MAXN = 100002; //int n, l, r; // //int head[MAXN]; @@ -35,9 +35,7 @@ //bool vis[MAXN]; //int siz[MAXN]; // -//Node cur[MAXN]; -//int cntc; -//Node all[MAXN]; +//Node arr[MAXN]; //int cnta; // //int tree[MAXN]; @@ -54,13 +52,15 @@ //} // //void add(int i, int v) { -// while (i <= r) { +// i++; +// while (i <= r + 1) { // tree[i] += v; // i += lowbit(i); // } //} // //int sum(int i) { +// i++; // int ret = 0; // while (i > 0) { // ret += tree[i]; @@ -103,7 +103,7 @@ // if (edge > r) { // return; // } -// cur[++cntc] = { maxv, edge }; +// arr[++cnta] = { maxv, edge }; // for (int e = head[u]; e; e = nxt[e]) { // int v = to[e]; // if (v != fa && !vis[v]) { @@ -112,49 +112,28 @@ // } //} // -//long long calc(int u) { -// long long ans = 0; +//long long calc(int u, int maxv, int edge) { // cnta = 0; -// for (int e = head[u]; e; e = nxt[e]) { -// int v = to[e]; -// if (!vis[v]) { -// cntc = 0; -// dfs(v, u, weight[e], 1); -// sort(cur + 1, cur + cntc + 1, NodeCmp); -// for (int i = 1; i <= cntc; i++) { -// ans -= 1LL * cur[i].maxv * (sum(r - cur[i].edge) - sum(l - cur[i].edge - 1)); -// add(cur[i].edge, 1); -// } -// for (int i = 1; i <= cntc; i++) { -// add(cur[i].edge, -1); -// } -// for (int i = 1; i <= cntc; i++) { -// all[++cnta] = cur[i]; -// } -// } -// } -// sort(all + 1, all + cnta + 1, NodeCmp); -// for (int i = 1; i <= cnta; i++) { -// ans += 1LL * all[i].maxv * (sum(r - all[i].edge) - sum(l - all[i].edge - 1)); -// add(all[i].edge, 1); -// } +// dfs(u, 0, maxv, edge); +// sort(arr + 1, arr + cnta + 1, NodeCmp); +// long long ans = 0; // for (int i = 1; i <= cnta; i++) { -// add(all[i].edge, -1); +// ans += 1LL * arr[i].maxv * (sum(r - arr[i].edge) - sum(l - arr[i].edge - 1)); +// add(arr[i].edge, 1); // } // for (int i = 1; i <= cnta; i++) { -// if (all[i].edge >= l) { -// ans += all[i].maxv; -// } +// add(arr[i].edge, -1); // } // return ans; //} // //long long solve(int u) { // vis[u] = true; -// long long ans = calc(u); +// long long ans = calc(u, 0, 0); // for (int e = head[u]; e; e = nxt[e]) { // int v = to[e]; // if (!vis[v]) { +// ans -= calc(v, weight[e], 1); // ans += solve(getCentroid(v, u)); // } // } From 3941edba9dc754e89a7336409075a23d6cf662e1 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Tue, 18 Nov 2025 15:13:04 +0800 Subject: [PATCH 9/9] modify code --- src/class183/Code07_Message1.java | 26 ++++++-------------------- src/class183/Code07_Message2.java | 23 +++++------------------ 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/src/class183/Code07_Message1.java b/src/class183/Code07_Message1.java index 3a37d281..05d6adb1 100644 --- a/src/class183/Code07_Message1.java +++ b/src/class183/Code07_Message1.java @@ -185,40 +185,26 @@ public static void dfs2(int cur, int fa, int deep) { } } - public static void calc(int u) { + public static void calc(int u, int dep, int effect) { cnta = 0; maxDep = 0; - // dfs1(u, 0, 1); - dfs2(u, 0, 1); + // dfs1(u, 0, dep); + dfs2(u, 0, dep); for (int i = 1; i <= cnta; i++) { - ans[qidArr[i]] += depCnt[timArr[i]]; + ans[qidArr[i]] += depCnt[timArr[i]] * effect; } for (int d = 1; d <= maxDep; d++) { depCnt[d] = 0; } - for (int e = headg[u]; e > 0; e = nextg[e]) { - int v = tog[e]; - if (!vis[v]) { - cnta = 0; - maxDep = 0; - // dfs1(v, u, 2); - dfs2(v, u, 2); - for (int i = 1; i <= cnta; i++) { - ans[qidArr[i]] -= depCnt[timArr[i]]; - } - for (int d = 1; d <= maxDep; d++) { - depCnt[d] = 0; - } - } - } } public static void solve(int u) { vis[u] = true; - calc(u); + calc(u, 1, 1); for (int e = headg[u]; e > 0; e = nextg[e]) { int v = tog[e]; if (!vis[v]) { + calc(v, 2, -1); solve(getCentroid(v, u)); } } diff --git a/src/class183/Code07_Message2.java b/src/class183/Code07_Message2.java index 4351447c..e3493370 100644 --- a/src/class183/Code07_Message2.java +++ b/src/class183/Code07_Message2.java @@ -103,38 +103,25 @@ // } //} // -//void calc(int u) { +//void calc(int u, int dep, int effect) { // cnta = 0; // maxDep = 0; -// dfs(u, 0, 1); +// dfs(u, 0, dep); // for (int i = 1; i <= cnta; i++) { -// ans[arr[i].qid] += depCnt[arr[i].tim]; +// ans[arr[i].qid] += depCnt[arr[i].tim] * effect; // } // for (int d = 1; d <= maxDep; d++) { // depCnt[d] = 0; // } -// for (int e = headg[u]; e; e = nextg[e]) { -// int v = tog[e]; -// if (!vis[v]) { -// cnta = 0; -// maxDep = 0; -// dfs(v, u, 2); -// for (int i = 1; i <= cnta; i++) { -// ans[arr[i].qid] -= depCnt[arr[i].tim]; -// } -// for (int d = 1; d <= maxDep; d++) { -// depCnt[d] = 0; -// } -// } -// } //} // //void solve(int u) { // vis[u] = true; -// calc(u); +// calc(u, 1, 1); // for (int e = headg[u]; e; e = nextg[e]) { // int v = tog[e]; // if (!vis[v]) { +// calc(v, 2, -1); // solve(getCentroid(v, u)); // } // }