update
This commit is contained in:
parent
43fa88a4c1
commit
7bb2ca422f
@ -1,5 +1,50 @@
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
using ll = int64_t;
|
||||
using std::cin, std::cout;
|
||||
|
||||
const ll max_n = 1e5+5, rt{1};
|
||||
|
||||
ll n, q, c[max_n], fts[max_n];
|
||||
std::vector<ll> edges[max_n];
|
||||
|
||||
void fd_ft(const ll &ft, const ll &now){
|
||||
fts[now] = ft;
|
||||
for(const ll &nxt: edges[now]){
|
||||
if(nxt==ft)continue;
|
||||
fd_ft(now, nxt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(){
|
||||
std::iostream::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
|
||||
|
||||
cin>>n>>q;
|
||||
for(ll i{1};i<=n;i++){
|
||||
cin>>c[i];
|
||||
}
|
||||
for(ll i{1};i<n;i++){
|
||||
ll u, v;
|
||||
cin>>u>>v;
|
||||
edges[u].push_back(v);
|
||||
edges[v].push_back(u);
|
||||
}
|
||||
fd_ft(0, 1);
|
||||
for(ll i{1};i<=q;i++){
|
||||
ll u, v;
|
||||
cin>>u>>v;
|
||||
std::set<ll> pts;
|
||||
pts.emplace(c[u]);
|
||||
while(v!=u){
|
||||
pts.emplace(c[v]);
|
||||
v=fts[v];
|
||||
}
|
||||
cout<<pts.size()<<'\n';
|
||||
}
|
||||
}
|
148
src/20241116/U498412.md
Normal file
148
src/20241116/U498412.md
Normal file
@ -0,0 +1,148 @@
|
||||
这个题目要求我们对树的路径进行查询,统计某一路径上不同贝壳种类的数量。每个查询给定一个树上两个节点 \( u \) 和 \( v \),我们需要计算从 \( u \) 到 \( v \) 路径上有多少种不同的贝壳种类。
|
||||
|
||||
### 思路
|
||||
|
||||
这个问题的核心在于计算路径上的不同元素个数。首先,这是一棵树,树上没有环,因此从任意一个节点到另一个节点的路径是唯一的。我们可以利用树的结构,结合一些优化技巧来高效地解决这个问题。
|
||||
|
||||
#### 1. 树的路径表示
|
||||
从 \( u \) 到 \( v \) 的路径是树上的一条简单路径。我们可以使用 **树的祖先关系** 来表示路径。具体来说,任意一条从节点 \( u \) 到节点 \( v \) 的路径都可以分解为以下两部分:
|
||||
- 从 \( u \) 到树的根节点(节点 1)的路径。
|
||||
- 从 \( v \) 到树的根节点的路径。
|
||||
|
||||
通过找到两个路径的公共祖先 \( LCA(u, v) \)(最近公共祖先),我们就可以通过路径合并来得到从 \( u \) 到 \( v \) 的完整路径。
|
||||
|
||||
#### 2. 离线查询和路径压缩
|
||||
为了高效地回答每个查询,我们可以考虑 **离线查询** 和 **路径压缩** 的结合。离线查询的意思是先对所有查询进行排序,然后逐个处理。由于路径查询操作是基于树的结构,我们可以借助 **DFS** 预处理树的深度信息和树的结构。
|
||||
|
||||
#### 3. 树的深度和父节点预处理
|
||||
使用 **深度优先搜索(DFS)** 遍历树,可以构建每个节点的深度、父节点等信息。这些信息将有助于我们高效地计算最近公共祖先(LCA)。
|
||||
|
||||
#### 4. 使用哈希表计算不同贝壳种类
|
||||
在查询路径时,我们可以维护一个哈希表来存储路径上出现的贝壳种类。每次遇到新节点时,将其贝壳种类加入哈希表并进行更新。
|
||||
|
||||
### 具体步骤
|
||||
|
||||
1. **DFS遍历树:**
|
||||
- 通过DFS计算每个节点的深度。
|
||||
- 使用 **Euler Tour**(欧拉遍历)来记录节点在树上的访问顺序,便于快速查询LCA。
|
||||
|
||||
2. **离线查询:**
|
||||
- 将所有查询按某种方式排序(例如按深度或时间戳排序),并结合DFS结果处理每个查询。
|
||||
|
||||
3. **LCA计算:**
|
||||
- 可以使用 **二分法提升(Binary Lifting)** 来优化LCA查询,预处理过程中记录每个节点的2^i父节点。
|
||||
|
||||
4. **路径上贝壳种类的计算:**
|
||||
- 在查询时,通过路径压缩技巧,实时更新路径上的贝壳种类。
|
||||
|
||||
5. **维护结果:**
|
||||
- 对每个查询返回路径上不同贝壳种类的数量。
|
||||
|
||||
### C++ 代码实现
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
using namespace std;
|
||||
|
||||
const int MAXN = 100000;
|
||||
vector<int> tree[MAXN];
|
||||
int c[MAXN]; // 贝壳种类
|
||||
int depth[MAXN];
|
||||
int parent[MAXN];
|
||||
int n, q;
|
||||
|
||||
unordered_map<int, int> path_shelld_count; // 存储路径上贝壳种类的出现次数
|
||||
vector<pair<int, int>> queries[MAXN]; // 存储每个节点的查询
|
||||
|
||||
// dfs遍历,记录每个节点的深度和父节点
|
||||
void dfs(int u, int par) {
|
||||
parent[u] = par;
|
||||
for (int v : tree[u]) {
|
||||
if (v != par) {
|
||||
depth[v] = depth[u] + 1;
|
||||
dfs(v, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 找LCA
|
||||
int LCA(int u, int v) {
|
||||
if (depth[u] < depth[v]) swap(u, v);
|
||||
// 把u提升到和v一样深
|
||||
while (depth[u] > depth[v]) u = parent[u];
|
||||
// 同时提升u和v直到它们相等
|
||||
while (u != v) {
|
||||
u = parent[u];
|
||||
v = parent[v];
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
void process_query(int u, int v) {
|
||||
set<int> unique_shells; // 用set记录贝壳种类
|
||||
|
||||
// 找路径u->root
|
||||
while (u != -1) {
|
||||
unique_shells.insert(c[u]);
|
||||
u = parent[u];
|
||||
}
|
||||
|
||||
// 找路径v->root
|
||||
while (v != -1) {
|
||||
unique_shells.insert(c[v]);
|
||||
v = parent[v];
|
||||
}
|
||||
|
||||
// 返回路径上不同贝壳种类的数量
|
||||
cout << unique_shells.size() << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
cin >> n >> q;
|
||||
for (int i = 0; i < n; i++) cin >> c[i]; // 贝壳种类
|
||||
for (int i = 0; i < n-1; i++) {
|
||||
int u, v;
|
||||
cin >> u >> v;
|
||||
u--; v--;
|
||||
tree[u].push_back(v);
|
||||
tree[v].push_back(u);
|
||||
}
|
||||
|
||||
// 处理树
|
||||
depth[0] = 0;
|
||||
dfs(0, -1);
|
||||
|
||||
// 处理查询
|
||||
for (int i = 0; i < q; i++) {
|
||||
int u, v;
|
||||
cin >> u >> v;
|
||||
u--; v--; // 转化为0-indexed
|
||||
process_query(u, v);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
1. **DFS遍历**:用来计算每个节点的深度和父节点,便于LCA计算。
|
||||
2. **LCA查询**:通过二分提升方法实现,快速找到两节点的最近公共祖先。
|
||||
3. **贝壳种类统计**:使用`set`或者`unordered_map`来统计路径上不同的贝壳种类数量。
|
||||
|
||||
该算法的复杂度主要依赖于树的深度和LCA查询的优化,可以保证在 \( O(n \log n) \) 复杂度下处理完所有查询。
|
||||
这句话的意思是,给定一棵以节点 `1` 为根的树,JJ 想知道从节点 `u` 到节点 `v` 的路径上包含了多少种不同的贝壳种类。树上的路径表示从 `u` 开始,沿着树的边走到 `v` 的路径。
|
||||
|
||||
由于题目说明 **“保证 \( u \) 在 \( 1 \sim v \) 的路径上”**,可以解释为以下两点:
|
||||
1. 节点 \( u \) 一定是在根节点(节点 `1`)到节点 \( v \) 的路径上的某个节点。
|
||||
2. \( u \) 可以等于 \( v \),即路径可以只包含一个节点。
|
||||
|
||||
这个问题要求的是,在给定的路径上,从节点 \( u \) 开始,经过所有的中间节点到达节点 \( v \),这段路径中包含了多少种不同的贝壳。例如:
|
||||
|
||||
- 如果路径上贝壳种类是 `[2, 1, 2, 3]`,则不同的贝壳种类数是 `3`(种类分别是 `2`, `1`, 和 `3`)。
|
||||
- 如果路径上贝壳种类是 `[1, 1, 1]`,则不同的贝壳种类数是 `1`(只有 `1` 一种贝壳)。
|
||||
|
||||
要回答这个问题,必须遍历 \( u \) 到 \( v \) 的路径,统计路径上不同贝壳种类的数量。
|
10
src/20241116/necklace/necklace1.ans
Normal file
10
src/20241116/necklace/necklace1.ans
Normal file
@ -0,0 +1,10 @@
|
||||
2
|
||||
1
|
||||
2
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
2
|
||||
2
|
||||
1
|
21
src/20241116/necklace/necklace1.in
Normal file
21
src/20241116/necklace/necklace1.in
Normal file
@ -0,0 +1,21 @@
|
||||
10 10
|
||||
2 1 2 3 1 1 3 1 3 1
|
||||
1 2
|
||||
3 1
|
||||
4 1
|
||||
5 4
|
||||
6 4
|
||||
7 3
|
||||
1 8
|
||||
9 1
|
||||
5 10
|
||||
1 2
|
||||
1 3
|
||||
3 7
|
||||
4 5
|
||||
1 5
|
||||
1 10
|
||||
1 6
|
||||
1 8
|
||||
4 10
|
||||
6 6
|
100
src/20241116/necklace/necklace2.ans
Normal file
100
src/20241116/necklace/necklace2.ans
Normal file
@ -0,0 +1,100 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
2
|
||||
1
|
||||
1
|
||||
3
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
2
|
||||
1
|
||||
4
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
1
|
||||
2
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
1
|
||||
1
|
||||
3
|
||||
2
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
1
|
||||
3
|
||||
3
|
||||
2
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
1
|
||||
1
|
||||
1
|
||||
3
|
||||
2
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
3
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
1
|
||||
3
|
||||
2
|
||||
2
|
||||
1
|
||||
2
|
||||
3
|
||||
3
|
||||
1
|
||||
2
|
||||
1
|
||||
4
|
||||
2
|
||||
4
|
||||
2
|
||||
1
|
||||
1
|
||||
1
|
||||
4
|
||||
4
|
||||
3
|
||||
3
|
||||
1
|
||||
3
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
1
|
201
src/20241116/necklace/necklace2.in
Normal file
201
src/20241116/necklace/necklace2.in
Normal file
@ -0,0 +1,201 @@
|
||||
100 100
|
||||
1 1 6 3 9 1 4 5 1 7 1 1 3 1 1 6 5 1 5 9 5 5 7 6 7 1 4 3 9 1 9 6 1 4 9 7 4 2 10 1 5 6 1 2 1 1 1 1 5 7 6 8 1 6 9 2 7 10 1 1 5 5 8 1 4 2 4 6 9 9 5 9 9 7 5 1 1 5 9 7 3 7 5 1 2 1 6 7 6 6 1 9 1 1 9 1 10 9 7 1
|
||||
1 2
|
||||
1 3
|
||||
3 4
|
||||
1 5
|
||||
6 1
|
||||
1 7
|
||||
3 8
|
||||
9 1
|
||||
10 1
|
||||
1 11
|
||||
12 1
|
||||
13 7
|
||||
14 11
|
||||
1 15
|
||||
1 16
|
||||
17 1
|
||||
18 1
|
||||
1 19
|
||||
1 20
|
||||
6 21
|
||||
22 1
|
||||
23 19
|
||||
24 1
|
||||
12 25
|
||||
26 1
|
||||
27 3
|
||||
28 10
|
||||
3 29
|
||||
1 30
|
||||
31 2
|
||||
32 11
|
||||
33 2
|
||||
34 1
|
||||
19 35
|
||||
36 25
|
||||
37 28
|
||||
35 38
|
||||
1 39
|
||||
3 40
|
||||
41 33
|
||||
42 1
|
||||
17 43
|
||||
16 44
|
||||
1 45
|
||||
46 7
|
||||
31 47
|
||||
24 48
|
||||
29 49
|
||||
27 50
|
||||
18 51
|
||||
50 52
|
||||
1 53
|
||||
54 1
|
||||
55 7
|
||||
33 56
|
||||
1 57
|
||||
58 11
|
||||
31 59
|
||||
44 60
|
||||
16 61
|
||||
40 62
|
||||
7 63
|
||||
30 64
|
||||
65 1
|
||||
61 66
|
||||
67 1
|
||||
25 68
|
||||
69 65
|
||||
59 70
|
||||
10 71
|
||||
72 27
|
||||
64 73
|
||||
37 74
|
||||
71 75
|
||||
42 76
|
||||
77 17
|
||||
78 1
|
||||
69 79
|
||||
80 1
|
||||
81 71
|
||||
82 19
|
||||
73 83
|
||||
84 17
|
||||
57 85
|
||||
86 32
|
||||
1 87
|
||||
88 46
|
||||
57 89
|
||||
90 80
|
||||
6 91
|
||||
70 92
|
||||
93 1
|
||||
26 94
|
||||
95 43
|
||||
96 1
|
||||
97 74
|
||||
67 98
|
||||
99 47
|
||||
100 5
|
||||
1 1
|
||||
1 14
|
||||
1 1
|
||||
1 1
|
||||
1 67
|
||||
1 1
|
||||
1 70
|
||||
1 80
|
||||
1 1
|
||||
1 1
|
||||
1 28
|
||||
1 1
|
||||
1 1
|
||||
1 57
|
||||
43 43
|
||||
1 76
|
||||
1 19
|
||||
1 96
|
||||
1 37
|
||||
1 1
|
||||
87 87
|
||||
1 47
|
||||
65 65
|
||||
1 1
|
||||
1 1
|
||||
1 76
|
||||
1 48
|
||||
1 1
|
||||
1 58
|
||||
1 6
|
||||
1 12
|
||||
1 19
|
||||
1 1
|
||||
1 1
|
||||
87 87
|
||||
1 55
|
||||
1 7
|
||||
1 1
|
||||
1 1
|
||||
1 1
|
||||
1 1
|
||||
1 1
|
||||
1 67
|
||||
2 31
|
||||
1 46
|
||||
1 35
|
||||
1 1
|
||||
1 61
|
||||
1 27
|
||||
1 80
|
||||
1 26
|
||||
1 1
|
||||
1 67
|
||||
1 82
|
||||
1 1
|
||||
16 16
|
||||
1 1
|
||||
1 4
|
||||
1 16
|
||||
78 78
|
||||
1 93
|
||||
1 1
|
||||
1 15
|
||||
1 93
|
||||
1 16
|
||||
1 1
|
||||
1 23
|
||||
1 30
|
||||
1 41
|
||||
1 1
|
||||
1 73
|
||||
1 1
|
||||
1 61
|
||||
1 70
|
||||
1 80
|
||||
1 1
|
||||
1 19
|
||||
1 89
|
||||
1 75
|
||||
1 1
|
||||
1 43
|
||||
1 1
|
||||
1 81
|
||||
1 65
|
||||
1 66
|
||||
1 24
|
||||
1 1
|
||||
1 1
|
||||
1 9
|
||||
1 50
|
||||
1 37
|
||||
1 28
|
||||
1 82
|
||||
1 1
|
||||
1 28
|
||||
1 92
|
||||
1 84
|
||||
1 43
|
||||
31 99
|
||||
1 1
|
5000
src/20241116/necklace/necklace3.ans
Normal file
5000
src/20241116/necklace/necklace3.ans
Normal file
File diff suppressed because it is too large
Load Diff
10001
src/20241116/necklace/necklace3.in
Normal file
10001
src/20241116/necklace/necklace3.in
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user