Description
已知无向连通图G由N个点,N-1条边组成。每个点有给定权值。现有M个操作,操作分为2种:操作1,将某点权值更改;操作2,询问从点A至点B路径上所有点的权值和。
Input
每个输入文件中仅包含一个测试数据。
第一行包含两个整数N,M。
第二行至第N行每行包含2个整数,A、B,表示节点A与节点B有一条边相连。
第N+1行包含N个整数,表示第N个点的初始权值。
第N+2行至第N+M+1行每行包含三个整数,K、A、B(若K=1,表示将点A权值改为B;若K=2表示询问点A至点B路径上所有点的权值和)
Output
输出文件若干行,分别对应每次操作2的答案。
Sample Input
3 2
1 2
1 3
1 2 3
2 1 3
2 2 3
Sample Output
4
6
Data Constraint
Hint
对于60%的数据,1<=N,M<=1000
对于100%的数据,2<=N<=30000;0<=M<=200000
.
.
.
.
.
分析
树链剖分+线段树
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct edge
{
int to,from;
}e[100010];
int head[100010],n,size[100010],dep[100010],fa[100010],id[100010],a[30010];
int rk[100010],top[100010],son[100010],cnt=0,tot=0,sum[400010],m;
void add(int x,int y)
{
e[++cnt].to=y;e[cnt].from=head[x];head[x]=cnt;
e[++cnt].to=x;e[cnt].from=head[y];head[y]=cnt;
}
void dfs1(int x,int father)
{
fa[x]=father;
dep[x]=dep[father]+1;
size[x]=1;
for (int i=head[x];i;i=e[i].from)
if (e[i].to!=father)
{
dfs1(e[i].to,x);
size[x]+=size[e[i].to];
if (size[e[i].to]>size[son[x]]) son[x]=e[i].to;
}
}
void dfs2(int x,int father)
{
id[x]=++tot,rk[tot]=x,top[x]=father;
if (son[x]) dfs2(son[x],father);
for (int i=head[x];i;i=e[i].from)
if (e[i].to!=son[x]&&e[i].to!=fa[x]) dfs2(e[i].to,e[i].to);
}
void build(int l,int r,int d)
{
if (l==r)
{
sum[d]=a[rk[l]];
return;
}
int mid=(l+r)/2;
build(l,mid,d*2);
build(mid+1,r,d*2+1);
sum[d]=sum[d*2]+sum[d*2+1];
}
void updata(int l,int r,int d,int x,int y)
{
if (l==r)
{
sum[d]=y;
return;
}
int mid=(l+r)/2;
if (x<=mid) updata(l,mid,d*2,x,y); else updata(mid+1,r,d*2+1,x,y);
sum[d]=sum[d*2]+sum[d*2+1];
}
int querysum(int l,int r,int d,int x,int y)
{
int ans=0,mid=(l+r)/2;
if (x<=l&&r<=y) return sum[d];
if (x<=mid) ans+=querysum(l,mid,d*2,x,y);
if (y>mid) ans+=querysum(mid+1,r,d*2+1,x,y);
sum[d]=sum[d*2]+sum[d*2+1];
return ans;
}
int getsum(int x,int y)
{
int ans=0;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=querysum(1,n,1,id[top[x]],id[x]);
x=fa[top[x]];
}
if (dep[x]<dep[y]) swap(x,y);
ans+=querysum(1,n,1,id[y],id[x]);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs1(1,0);
fa[1]=1;
dfs2(1,1);
build(1,n,1);
while (m--)
{
int k,x,y;
scanf("%d%d%d",&k,&x,&y);
if (k==1) updata(1,n,1,id[x],y); else printf("%d\n",getsum(x,y));
}
return 0;
}