dsu+长链剖分

Posted ytytzzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dsu+长链剖分相关的知识,希望对你有一定的参考价值。

dsu,对于无修改子树查询,并且操作支持undo的问题

暴力dfs,对于每个节点,对所有轻儿子dfs下去,然后再消除轻儿子的影响

dfs重儿子,然后dfs暴力恢复轻儿子们的影响,再把当前节点影响算进去

就有了整棵子树的信息了,时间复杂度O(nlogn)

经典例题:http://codeforces.com/contest/600/problem/E

技术图片
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int N = 1e5 + 5;
 8 
 9 int n, c[N];
10 
11 int cnt[N], maxCnt;
12 
13 int siz[N], son[N];
14 
15 vector <int> e[N];
16 
17 ll ans[N], sum[N];
18 
19 void dfs1(int u, int fr) 
20     siz[u] = 1;
21     for (int v : e[u]) 
22         if (v == fr) continue;
23         dfs1(v, u);
24         siz[u] += siz[v];
25         if (siz[v] > siz[son[u]]) son[u] = v;
26     
27 
28 
29 void update(int x, int y) 
30     sum[cnt[x]] -= x;
31     cnt[x] += y;
32     sum[cnt[x]] += x;
33     if (cnt[x] > maxCnt) maxCnt = cnt[x];
34     if (sum[maxCnt] == 0) maxCnt --;
35 
36 
37 void dfs3(int u, int fr, int val) 
38     update(c[u], val);
39     for (int v : e[u]) 
40         if (v == fr) continue;
41         dfs3(v, u, val);
42     
43 
44 
45 void dfs2(int u, int fr) 
46     for (int v : e[u]) 
47         if (v == fr || v == son[u]) continue;
48         dfs2(v, u), dfs3(v, u, -1);
49     
50     if (son[u]) dfs2(son[u], u);
51     for (int v : e[u]) 
52         if (v == fr || v == son[u]) continue;
53         dfs3(v, u, 1);
54     
55     update(c[u], 1);
56     ans[u] = sum[maxCnt];
57 
58 
59 int main() 
60     ios::sync_with_stdio(false);
61     cin >> n;
62     for (int i = 1; i <= n; i ++)
63         cin >> c[i];
64     for (int u, v, i = 1; i < n; i ++) 
65         cin >> u >> v;
66         e[u].push_back(v);
67         e[v].push_back(u);
68     
69     dfs1(1, 1), dfs2(1, 1);
70     for (int i = 1; i <= n; i ++)
71         cout << ans[i] <<  ;    
72     cout << endl;
73     return 0;
74 
View Code

 

以上是关于dsu+长链剖分的主要内容,如果未能解决你的问题,请参考以下文章

长链剖分随想

长链剖分小结

模板K级祖先(长链剖分)

长链剖分 解 k级祖先问题

[算法学习] 长链剖分

bzoj3252攻略(长链剖分+贪心)