树链剖分 模板
关于树链剖分
模板:
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 }