题解:dfs序+树链剖分
#include
#include
#include
#include
#include
#define N 200003
#define LL long long
using namespace std;
int n,m,t,tot,sz;
LL tr[N*4],delta[N*4];
int point[N],next[N],v[N],belong[N],size[N],son[N],fa[N],deep[N];
int pos[N],l[N],r[N];
void add(int x,int y)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int f)
{
size[x]=1;
for (int i=point[x];i;i=next[i])
if (v[i]!=f)
{
deep[v[i]]=deep[x]+1;
dfs(v[i],x);
fa[v[i]]=x;
size[x]+=size[v[i]];
if (size[v[i]]>size[son[x]])
son[x]=v[i];
}
}
void build(int k,int chain)
{
belong[k]=chain; pos[k]=++sz;
l[k]=sz; r[k]=sz;
if (!son[k]) return;
build(son[k],chain);
for (int i=point[k];i;i=next[i])
if (v[i]!=fa[k]&&v[i]!=son[k])
build(v[i],v[i]);
r[k]=sz;
}
void pushdown(int now,int l,int r)
{
if (!delta[now]) return;
delta[now<<1]+=delta[now];
delta[now<<1|1]+=delta[now];
int mid=(l+r)/2;
tr[now<<1]+=(LL)(mid-l+1)*delta[now];
tr[now<<1|1]+=(LL)(r-mid)*delta[now];
delta[now]=0;
}
LL query(int now,int l,int r,int ll,int rr)
{
if (l>=ll&&r<=rr) return tr[now];
pushdown(now,l,r);
int mid=(l+r)/2;
LL ans=0;
if (ll<=mid) ans+=query(now<<1,l,mid,ll,rr);
if (rr>mid) ans+=query(now<<1|1,mid+1,r,ll,rr);
return ans;
}
void change(int now,int l,int r,int ll,int rr,LL v)
{
if (l>=ll&&r<=rr){
tr[now]+=(LL)v*(r-l+1);
delta[now]+=v;
return;
}
pushdown(now,l,r);
int mid=(l+r)/2;
if (ll<=mid) change(now<<1,l,mid,ll,rr,v);
if (rr>mid) change(now<<1|1,mid+1,r,ll,rr,v);
tr[now]=tr[now<<1]+tr[now<<1|1];
}
void solve(int x,int y,LL v)
{
while (belong[x]!=belong[y])
{
if (deep[belong[x]]deep[y]) swap(x,y);
change(1,1,n,pos[x],pos[y],v);
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&n);
for (int i=1;i