题意:
给你一棵树,两种操作:
1.将x到y的路径上的所有点的权值+k
2.将x到y路径上的所有边的权值+k
所有操作结束后问你所有的点权和所有的边权
题解:
这道题用树链剖分估计会T,因为它是
n
l
o
g
2
n
nlog^2n
nlog2n的。
由于每次加的一定是一条链或者两条链,那么我们只需要用前缀和的思想去做即可,也就是说加点权的时候在x的位置加上k,y的位置+k,lca的位置-k,因为x和y的值合并了之后就变成2k,需要减掉一个。然后在lca的父亲位置-k。
边权的话只需要在x,y的位置+k,lca的位置-2k即可。我们将边权当做儿子节点处理,并且这是普遍解决边权存储位置的方法。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
ll sum_p[N],sum_e[N],flag[N];
struct node
{
int to,next;
}e[N*2];
int cnt,head[N];
void add(int x,int y)
{
e[cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt++;
}
int fa[N][25],dep[N];
void dfs(int x,int f)
{
fa[x][0]=f;
dep[x]=dep[f]+1;
for(int i=head[x];~i;i=e[i].next)
{
int ne=e[i].to;
if(ne==f)
continue;
dfs(ne,x);
}
}
int n,m;
void deal()
{
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)return x;
for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int xx[N],yy[N];
void dfs_p(int x,int f)
{
for(int i=head[x];~i;i=e[i].next)
{
int ne=e[i].to;
if(ne==f)
continue;
dfs_p(ne,x);
sum_p[x]+=sum_p[ne]-flag[ne];
}
}
void dfs_e(int x,int f)
{
for(int i=head[x];~i;i=e[i].next)
{
int ne=e[i].to;
if(ne==f)
continue;
dfs_e(ne,x);
sum_e[x]+=sum_e[ne];
}
}
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
int x,y;
ll k;
char op[10];
scanf("%d%d",&n,&m);
cnt=0;
for(int i=1;i<=n;i++)
sum_p[i]=sum_e[i]=flag[i]=0,head[i]=-1;
for(int i=1;i<n;i++)
scanf("%d%d",&xx[i],&yy[i]),add(xx[i],yy[i]),add(yy[i],xx[i]);
dfs(1,0),deal();
while(m--)
{
scanf("%s%d%d%lld",op,&x,&y,&k);
int l=lca(x,y);
if(op[3]=='1')
sum_p[x]+=k,sum_p[y]+=k,sum_p[l]-=k,flag[l]+=k;
else
sum_e[x]+=k,sum_e[y]+=k,sum_e[l]-=2*k;
}
dfs_p(1,0),dfs_e(1,0);
printf("Case #%d:\n",++cas);
for(int i=1;i<=n;i++)
{
printf("%lld",sum_p[i]);
if(i==n)
printf("\n");
else
printf(" ");
}
if(n==1)
printf("\n");
for(int i=1;i<n;i++)
{
printf("%lld",dep[xx[i]]>dep[yy[i]]?sum_e[xx[i]]:sum_e[yy[i]]);
if(i==n-1)
printf("\n");
else
printf(" ");
}
}
return 0;
}