题目链接
求子树信息,这样一类的题目,往往可以使用Dsu on Tree这样的启发式合并的做法来实现。
我们直接对于轻儿子每次均不保留,并且先查轻儿子,再查重儿子,以此来满足时间复杂度。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #include <bitset> //#include <unordered_map> //#include <unordered_set> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define eps 1e-4 #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r #define MP(a, b) make_pair(a, b) using namespace std; typedef unsigned long long ull; typedef unsigned int uit; typedef long long ll; const int maxN = 1e5 + 7; int N, Q, head[maxN], cnt, col[maxN]; struct Eddge { int nex, to; Eddge(int a=-1, int b=0):nex(a), to(b) {} } edge[maxN]; inline void addEddge(int u, int v) { edge[cnt] = Eddge(head[u], v); head[u] = cnt++; } int siz[maxN], Wson[maxN] = {0}; void pre_dfs(int u) { siz[u] = 1; for(int i=head[u], v; ~i; i=edge[i].nex) { v = edge[i].to; pre_dfs(v); if(siz[v] > siz[Wson[u]]) Wson[u] = v; siz[u] += siz[v]; } } int num[maxN] = {0}, have = 0, ans[maxN], dfn[maxN], rid[maxN], tot = 0; void dfs(int u, bool keep) { dfn[u] = ++tot; rid[tot] = u; for(int i=head[u], v; ~i; i=edge[i].nex) { v = edge[i].to; if(v == Wson[u]) continue; dfs(v, false); } if(Wson[u]) { dfs(Wson[u], true); } if(!num[col[u]]) have++; num[col[u]]++; for(int i=head[u], v, id; ~i; i=edge[i].nex) { v = edge[i].to; if(v == Wson[u]) continue; for(int j=dfn[v]; j<dfn[v] + siz[v]; j++) { id = rid[j]; if(!num[col[id]]) have++; num[col[id]] ++; } } ans[u] = have; if(!keep) { for(int i=dfn[u], id; i<dfn[u] + siz[u]; i++) { id = rid[i]; num[col[id]]--; if(!num[col[id]]) have--; } } } inline void init() { cnt = 0; for(int i=1; i<=N; i++) head[i] = -1; } int main() { scanf("%d", &N); init(); for(int i=2, ff; i<=N; i++) { scanf("%d", &ff); addEddge(ff, i); } for(int i=1; i<=N; i++) scanf("%d", &col[i]); pre_dfs(1); dfs(1, true); scanf("%d", &Q); int op; while(Q--) { scanf("%d", &op); printf("%dn", ans[op]); } return 0; }
最后
以上就是雪白西装最近收集整理的关于小A的礼物【Dsu on Tree】的全部内容,更多相关小A的礼物【Dsu内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复