树链剖分 模板

关于树链剖分

 

模板:

 1 const int MAXN = 20010;
 2 struct Edge
 3 {
 4     int to,next;
 5 } edge[MAXN*2];
 6 int head[MAXN],tot;
 7 
 8 int top[MAXN];//top[v]表示v所在的重链的顶端节点
 9 int fa[MAXN]; //父亲节点
10 int deep[MAXN];//深度
11 int num[MAXN];//num[v]表示以v为根的子树的节点数
12 int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置
13 int fp[MAXN];//和p数组相反
14 int son[MAXN];//重儿子
15 int pos;
16 
17 int n;
18 
19 void init()
20 {
21     tot = 0;
22     memset(head,-1,sizeof(head));
23     pos = 1;//序号其实是从1开始?
24     memset(son,-1,sizeof(son));
25 }
26 void addedge(int u,int v)
27 {
28     edge[tot].to = v;
29     edge[tot].next = head[u];
30     head[u] = tot++;
31 }
32 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son
33 {
34     deep[u] = d;
35     fa[u] = pre;
36     num[u] = 1;
37     for(int i = head[u]; i != -1; i = edge[i].next)
38     {
39         int v = edge[i].to;
40         //因为路径是双向的,所以不能等于父及诶单
41         if(v != pre)
42         {
43             //先递归地找到儿子节点的深度,父节点,子节点数目等信息
44             dfs1(v,u,d+1);
45             //更新u节点的儿子数目
46             num[u] += num[v];
47             if(son[u] == -1 || num[v] > num[son[u]])//求出重儿子
48                 son[u] = v;
49         }
50     }
51 }
52 
53 //因为对于轻儿子来说,top[u]=u,对于重儿子来说,如果son[v]!=-1,那么top[v]=top[son[v]]
54 void getpos(int u,int sp) //第二遍dfs求出top和p
55 {
56     top[u] = sp;
57     //先找重儿子
58     if(son[u] != -1)
59     {
60         //把边的位置标记一下
61         p[u] = pos++;
62         //fp相当于是p的反函数?
63         fp[p[u]] = u;
64         //更新重儿子
65         getpos(son[u],sp);
66     }
67     //如果到了叶子节点
68     else
69     {
70         //不再向下dfs
71         p[u] = pos++;
72         fp[p[u]] = u;
73         return;
74     }
75     //更新其他的节点
76     for(int i = head[u] ; i != -1; i = edge[i].next)
77     {
78         int v = edge[i].to;
79         if(v != son[u] && v != fa[u])
80             getpos(v,v);
81     }
82 }

 

posted @ 2017-08-27 17:06  Wally的博客  阅读(157)  评论(0编辑  收藏  举报