19.10.01 acm E:Lowest Common Ancestor
Posted xjqxjq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19.10.01 acm E:Lowest Common Ancestor相关的知识,希望对你有一定的参考价值。
题目描述
一棵有根树,对于每个点 $i$ ,求 $\sum_j=1^i-1w_lca(i,j)$
数据范围
$n \le 2 \times 10^5,1 \le w_i \le 10^4$
题解
我们可以考虑枚举 $lca$ 去更新答案
对于每个点 $x$ ,如果它成为两个点的 $lca$ ,那这两个点肯定来自不同的子树
那我们可以建立一个线段树表示这个区间的答案总和(?),然后进行线段树合并即可
具体地话就是考虑合并到 $x,y$ 两个节点上,那 $x$ 的左儿子会对 $y$ 的右儿子造成贡献,同理 $y$ 的左儿子会对 $x$ 的右儿子造成贡献,所以我们再多维护一个区间有多少个数出现即可
代码
#include <bits/stdc++.h> using namespace std; const int N=2e5+5,M=N*50; int a[N],TT,n,T[N],t,nx[N],hd[N],V[N]; int s[M],f[M],ls[M],rs[M],tg[M]; void add(int u,int v) nx[++t]=hd[u];V[hd[u]=t]=v; #define mid ((l+r)>>1) void insert(int &x,int l,int r,int v) s[x=++t]++; if (l==r) return; if (mid>=v) insert(ls[x],l,mid,v); else insert(rs[x],mid+1,r,v); void down(int x) if (ls[x]) f[ls[x]]+=tg[x],tg[ls[x]]+=tg[x]; if (rs[x]) f[rs[x]]+=tg[x],tg[rs[x]]+=tg[x]; tg[x]=0; int merge(int x,int y,int c,int d,int v) if (!x && !y) return 0; if (!x)f[y]+=d*v;tg[y]+=d*v;return y; if (!y)f[x]+=c*v;tg[x]+=c*v;return x; down(x);down(y);int z=++t; ls[z]=merge(ls[x],ls[y],c,d,v); rs[z]=merge(rs[x],rs[y],c+s[ls[y]],d+s[ls[x]],v); f[z]=f[ls[z]]+f[rs[z]]; s[z]=s[ls[z]]+s[rs[z]]; return z; void dfs(int x,int fr) insert(T[x],1,n,x); for (int i=hd[x];i;i=nx[i]) if (V[i]!=fr) dfs(V[i],x), T[x]=merge(T[x],T[V[i]],0,0,a[x]); void put(int x,int l,int r) if (l==r) if (l>1) printf("%d\n",f[x]);return; down(x);put(ls[x],l,mid);put(rs[x],mid+1,r); void work() t=0; for (int i=1;i<=n;i++) scanf("%d",&a[i]),hd[i]=0; for (int i=2,x;i<=n;i++) scanf("%d",&x),add(x,i);t=0; dfs(1,0);put(T[1],1,n); for (int i=1;i<=t;i++) ls[i]=rs[i]=tg[i]=f[i]=s[i]=0; int main() while(~scanf("%d",&n)) work(); return 0;
以上是关于19.10.01 acm E:Lowest Common Ancestor的主要内容,如果未能解决你的问题,请参考以下文章
python 改编自https://github.com/diafygi/acme-tiny/blob/master/acme_tiny.py,FTP文件上传或者阿里云OSS上传.https://fi