2 条题解

  • 0
    @ 2026-8-5 11:35:34

    让我们对kevin的代码稍加解释

    函数dfs1:在树上跑dfs,预处理出每个节点的深度,父节点,以及重儿子。

    函数dfs2:跑第二遍dfs,记录dfs序以及dfs序反数组(下标和键值互换),每条重链的顶端。

    结构体:线段树,以每个节点的dfs序作为下标,具体原因见后。

    函数pushup,bt,change,query,详见线段树

    函数solve:计算两个节点之间路径的节点权值总和,即最终答案。如何计算?注意到dfs2是重儿子优先遍历,一条重链上的节点都是dfs序连续的,只需要在LCA过程中每一次跳跃都计算本条重链的和,跳跃完之后输出答案即可。

    • 0
      @ 2025-12-9 19:52:14
      #include<bits/stdc++.h>
      using namespace std;
      const int N=5e5+10;
      #define int long long
      vector<int>G[N];
      int dep[N],fa[N],son[N],siz[N],top[N],dfn[N],_dfn[N],tsp;
      void dfs1(int x,int f)
      {
      	dep[x]=dep[f]+1;fa[x]=f;siz[x]=1;int mx=0;
      	for(int y:G[x])if(y!=f)
      	{
      		dfs1(y,x);
      		siz[x]+=siz[y];
      		if(mx<siz[y])mx=siz[y],son[x]=y;
      	}
      }
      void dfs2(int x,int tp)
      {
      	top[x]=tp;dfn[x]=++tsp;_dfn[tsp]=x;
      	if(son[x])dfs2(son[x],tp);
      	for(int y:G[x])if(y!=fa[x]&&y!=son[x])dfs2(y,y);
      }
      #define lc(p) (p<<1)
      #define rc(p) (p<<1|1)
      struct node{int l,r,s;}tr[N<<2];int a[N];
      void pushup(int p){tr[p].s=tr[lc(p)].s+tr[rc(p)].s;}
      void bt(int p,int l,int r)
      {
      	tr[p]={l,r,0};
      	if(l==r){tr[p].s=a[_dfn[l]];return;}
      	int mid=(l+r)>>1;
      	bt(lc(p),l,mid),bt(rc(p),mid+1,r);
      	pushup(p);
      }
      void change(int p,int x,int k)
      {
      	if(tr[p].r<x||tr[p].l>x)return;
      	if(tr[p].l==tr[p].r)
      	{
      		tr[p].s+=k;
      		return ;
      	}
      	change(lc(p),x,k);change(rc(p),x,k);
      	pushup(p);
      }
      int query(int p,int l,int r)
      {
      	if(tr[p].r<l||tr[p].l>r)return 0;
      	if(l<=tr[p].l&&tr[p].r<=r)return tr[p].s;
      	return query(lc(p),l,r)+query(rc(p),l,r);
      }
      int solve(int x,int y)
      {
      	int ret=0;
      	for(;top[x]!=top[y];x=fa[top[x]])
      	{
      		if(dep[top[x]]<dep[top[y]])swap(x,y);
      		ret+=query(1,dfn[top[x]],dfn[x]);
      	}
      	if(dep[x]>dep[y])swap(x,y);
      	ret+=query(1,dfn[x],dfn[y]);
      	return ret;
      }
      signed main()
      {
      	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
      	int n,q;cin>>n>>q;
      	for(int i=1;i<=n;i++)cin>>a[i];
      	for(int i=1;i<n;i++)
      	{
      		int x,y;cin>>x>>y;x++,y++;
      		G[x].push_back(y);
      		G[y].push_back(x);
      	}
      	dfs1(1,0);dfs2(1,1);
      	bt(1,1,n);
      	while(q--)
      	{
      		int op,x,y;cin>>op>>x>>y;x++;y++;
      		if(op==0)change(1,dfn[x],y-1);
      		else cout<<solve(x,y)<<'\n';
      	}
      	return 0;
      }
      
      • 1

      顶点加路径和(Vertex Add Path Sum)

      信息

      ID
      8112
      时间
      1000ms
      内存
      1024MiB
      难度
      7
      标签
      递交数
      19
      已通过
      9
      上传者