ACM模板库

ACM模板库


重链剖分

<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/edf804cd7e679f9d3627ee67473ffbe0" alt="" /> <img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/da21ebe0f39ac5e853140406db166e92" alt="" /></p> <pre><code class="language-cpp">const int maxn=1e5+10; struct Edge{ int next; int to; }; Edge edge[maxn &lt;&lt; 1]; int rt, n, m, r, cnt; int num[maxn], head[maxn], f[maxn], d[maxn], size[maxn]; int son[maxn], rk[maxn], top[maxn], id[maxn]; void dfs1(int u, int fa, int depth){ //当前节点、父节点、层次深度 f[u] = fa; d[u] = depth; size[u] = 1; //这个点本身size=1 for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if(v == fa) continue; dfs1(v, u, depth + 1); //层次深度+1 size[u] += size[v]; //子节点的size已被处理,用它来更新父节点的size if(size[v] &gt; size[son[u]]) son[u] = v; //选取size最大的作为重儿子 } } void dfs2(int u, int t){ //当前节点、重链顶端 top[u] = t; id[u] = ++cnt; //标记dfs序 rk[cnt] = u; //序号cnt对应节点u if(!son[u]) return; dfs2(son[u], t); /*我们选择优先进入重儿子来保证一条重链上各个节点dfs序连续, 一个点和它的重儿子处于同一条重链,所以重儿子所在重链的顶端还是t*/ for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; //一个点位于轻链底端,那么它的top必然是它本身 if(v != son[u] &amp;&amp; v != f[u]) dfs2(v,v); } } int sum(int x,int y){//x到y路径和 int ret = 0; while(top[x] != top[y]){ if(d[top[x]] &lt; d[top[y]]) swap(x, y); (ret += query(id[top[x]], id[x], rt)) %= mod; x = f[top[x]]; } if(id[x] &gt; id[y]) swap(x,y); return (ret + query(id[x], id[y], rt)) % mod; } void build(int l,int r,int x)//这个函数主要看构造树,num[rk[l]] { if(l==r) { a[x].sum=v[rk[l]],a[x].l=a[x].r=l; return; } int mid=l+r&gt;&gt;1; a[x].ls=cnt++,a[x].rs=cnt++; build(l,mid,a[x].ls),build(mid+1,r,a[x].rs); a[x].l=a[a[x].ls].l,a[x].r=a[a[x].rs].r; pushup(x); } //进入 int main(){ memset(head, -1, sizeof(head)); dfs1(root,0,1);//root dfs1(root,root); } </code></pre>

页面列表

ITEM_HTML