题意:
两个操作,改点的权值和查询路径和
0 i j:从i点到j点的权值和
1 i v: 第i点的权值变成v
裸剖
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 60005;
int dep[maxn],siz[maxn],fa[maxn],id[maxn],son[maxn],val[maxn],top[maxn],pre_val[maxn];
int topw,head[maxn],cnt;
///dep 深度 siz个数 fa父 top祖 son重儿子 val值
/// e数组 初始入边 edge数组存边
struct Edge
{
int to,next;
} edge[maxn*2];
struct treex
{
int x,y,val;
} e[maxn];
void add(int u,int v )
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void dfs1(int u,int f,int d)
{
dep[u]=d;
siz[u]=1;
son[u]=0;
fa[u]=f;
for(int i =head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[u])
continue;
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])
son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
id[u]=++topw;
if(son[u])
dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[u]||v==son[u])
continue;
dfs2(v,v);
}
}
struct node
{
int left,right,sum;
}tree[maxn*4];
void push_up(int i)
{
tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
void build(int i,int left,int right)
{
tree[i].left=left;
tree[i].right=right;
if(left==right)
{
tree[i].sum=val[left];
return ;
}
int mid=(tree[i].left+tree[i].right)>>1;
build(i<<1,left,mid);
build(i<<1|1,mid+1,right);
push_up(i);
}
void update(int i,int aim,int w)
{
if(tree[i].left==tree[i].right&&tree[i].left==aim)
{
tree[i].sum=w;
return ;
}
int mid=(tree[i].left+tree[i].right)>>1;
if(aim<=mid)
update(i<<1,aim,w);
else
update(i<<1|1,aim,w);
push_up(i);
}
int query(int i,int left,int right)
{
if(tree[i].left>=left&&tree[i].right<=right)
return tree[i].sum;
int mid=(tree[i].left+tree[i].right)>>1;
if(right<=mid)
return query(i<<1,left,right);
else if(left>mid)
return query(i<<1|1,left,right);
else
return query(i<<1,left,mid)+query(i<<1|1,mid+1,right);
}
void change(int u,int v)
{
int ans=0;
int fu = top[u],fv = top[v];
while(fu != fv)
{
if(dep[fu] < dep[fv])
{
swap(u,v);swap(fu,fv);
}
ans+=query(1,id[fu],id[u]);
u = fa[fu];
fu = top[u];
}
if(dep[u] > dep[v]) swap(u,v);
ans+=query(1,id[u],id[v]);
printf("%d\n",ans);
return ;
}
int main()
{
int n,m,s;
int t;
scanf("%d",&t);
for(int cs=1;cs<=t;cs++)
{
cnt=0,topw=0;
printf("Case %d:\n",cs);
scanf("%d",&n);
memset(head,-1,sizeof(head));
memset(son,0,sizeof(son));
memset(dep,0,sizeof(dep));
memset(siz,0,sizeof(siz));
for(int i=1;i<=n;i++)
{
scanf("%d",&pre_val[i]);
}
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
u++,v++;
add(u,v);
add(v,u);
}
topw=0;
dfs1(1,0,1);
dfs2(1,1);
//将之前给出的边的权值,赋给点。
for(int i=1;i<=n;i++)
{
val[id[i]]=pre_val[i];
}
build(1,1,topw);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int ok,x,y;
scanf("%d",&ok);
scanf("%d%d",&x,&y);
if(ok==1)
{
x++;
update(1,id[x],y);
}
else
{
x++,y++;
change(x,y);
}
}
}
return 0;
}