WOJ2232 树上修改4(方法同上上篇,树剖)
【题目描述】
有n个节点N-1条边,这是一颗树,有2个操作:
1 x v:表示将节点x的权值+v
2 x y:表示查询x到y的路径权值和
【输入格式】
第一行是数N,表示N个节点,接下一行是n个数,表示每个节点的初始权值。
接下来n-1行,每行描述了n-1条边。
接下来是一个数q表示有q次查询与询问 接下来q行,格式如题
【输出格式】
对于每次询问,输出路径权值和。
【样例输入】
3
1 2 3
1 2
2 3
3
1 1 2
1 2 3
2 1 3
【样例输出】
11
【题目分析】
BZOJ1036树的统计题解传送门:https://blog.csdn.net/g21glf/article/details/82956343
我的天,这两道题基本没区别啊!!!取了一个最大值,改了一下路径修改方式,就是一道题了。。。所以照搬啦
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+10;
struct node{
int y,next;
}edge[MAXN<<1];
int head[MAXN];
int dfn[MAXN],son[MAXN],depth[MAXN],fa[MAXN],siz[MAXN],a[MAXN];
int l,x,y,n,q,tot;
char s[10];
int rec[MAXN],top[MAXN];
void add(int x,int y)
{
l++;
edge[l].y=y;
edge[l].next=head[x];
head[x]=l;
}
void dfs1(int x,int f)
{
fa[x]=f;
son[x]=0;
siz[x]=1;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].y;
if(v!=f)
{
depth[v]=depth[x]+1;
dfs1(v,x);
siz[x]+=siz[v];
if(siz[son[x]]<siz[v])
son[x]=v;
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
dfn[x]=++tot;
rec[dfn[x]]=x;
if(son[x])
dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].y;
if(v!=fa[x]&&v!=son[x])
dfs2(v,v);
}
}
struct point{
int l,r,sum;
}tr[4*MAXN];
void push_up(int root)
{
tr[root].sum=tr[root<<1].sum+tr[root<<1|1].sum;
}
void build(int root,int l,int r)
{
tr[root].l=l;tr[root].r=r;
if(l==r)
{
tr[root].sum=a[rec[l]];
return ;
}
int mid=l+r>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
push_up(root);
}
void update(int root,int x,int y)
{
if(tr[root].l==x&&tr[root].r==x)
{
tr[root].sum+=y;
return ;
}
int mid=tr[root].l+tr[root].r>>1;
if(x<=mid)
update(root<<1,x,y);
if(x>mid)
update(root<<1|1,x,y);
push_up(root);
}
int querysum(int root,int l,int r)
{
if(tr[root].l==l&&tr[root].r==r)
return tr[root].sum;
int mid=tr[root].l+tr[root].r>>1;
if(r<=mid)
return querysum(root<<1,l,r);
if(l>mid)
return querysum(root<<1|1,l,r);
if(l<=mid&&r>mid)
{
int s1=querysum(root<<1,l,mid);
int s2=querysum(root<<1|1,mid+1,r);
return s1+s2;
}
}
int findsum(int x,int y)
{
int f1=top[x],f2=top[y],ret=0;
while(f1!=f2)
{
if(depth[f1]<depth[f2])
{
swap(f1,f2);
swap(x,y);
}
ret+=querysum(1,dfn[f1],dfn[x]);
x=fa[f1],f1=top[x];
}
if(x==y)
return ret+querysum(1,dfn[x],dfn[y]);
if(depth[x]>depth[y])
swap(x,y);
return ret+querysum(1,dfn[x],dfn[y]);
}
int main()
{
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
scanf("%d",&q);
while(q--)
{
int cz;
scanf("%d%d%d",&cz,&x,&y);
if(cz==1)
update(1,dfn[x],y);
else
printf("%d\n",findsum(x,y));
}
return 0;
}