这道题好水啊。。。不知道为什么Luogu上给到紫色难度。信息课无聊就秒掉了。。。
很容易想到将每两个点之间的点权+1,直接树剖/差分乱搞即可。
但是要注意,\(A_2\)到\(A_N\)之间的点被当成起点和终点加了两次,所以输出的时候要-1。
#includeconst int max_n=300000+5;int N,cnt;int top[max_n],siz[max_n],son[max_n],father[max_n],depth[max_n];int first_edge[max_n],A[max_n],C[max_n];struct Edge{ int to,next_edge;}edge[max_n<<1];inline int read(){ register int x=0; register char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) { x=(x<<1)+(x<<3)+ch-'0'; ch=getchar(); } return x;}inline void add_edge(int x,int y){ edge[++cnt].to=y; edge[cnt].next_edge=first_edge[x]; first_edge[x]=cnt;}inline void dfs1(int x,int fa){ depth[x]=depth[fa]+1; father[x]=fa; siz[x]=1; int maxx=-1; for(register int k=first_edge[x];k;k=edge[k].next_edge) { if(edge[k].to!=fa) { dfs1(edge[k].to,x); siz[x]+=siz[edge[k].to]; if(siz[edge[k].to]>maxx) { maxx=siz[edge[k].to]; son[x]=edge[k].to; } } }}inline void dfs2(int x,int topf){ top[x]=topf; if(!son[x]) return; dfs2(son[x],topf); for(register int k=first_edge[x];k;k=edge[k].next_edge) if(edge[k].to!=father[x] && edge[k].to!=son[x]) dfs2(edge[k].to,edge[k].to); return;}inline int LCA(int x,int y){ while(top[x]!=top[y]) { if(depth[top[x]]