1.将一棵树转化成一个序列
2.树中路径转化成logn段连续区间
重儿子
重边
重链:对于轻儿子,重链自它起始
重儿子在它父节点的重链上
dfs中优先遍历重儿子 ,保证重链上所有点的编号是连续的
定理:树中任意一条路径均可拆分成O(logn)个重链(即为logn个连续区间)
#include <iostream>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
const int N = 1e5+10,M=2e5+10;
int n,m;
int h[N],w[N],e[M],ne[M],idx;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dep[N],sz[N],son[N],fa[N],p[N];
int dfn[N],wt[N],cnt;
void dfs1(int u,int f,int d){
dep[u]=d;
sz[u]=1;
fa[u]=f;
for(int i=h[u];~i;i=ne[i]){
int k=e[i];
if(k==f)continue;
dfs1(k,u,d+1);
sz[u]+=sz[k];
if(sz[k]>sz[son[u]])son[u]=k;
}
}
void dfs2(int u,int f){
p[u]=f;
dfn[u]=++cnt;
wt[cnt]=w[u];
if(!son[u])return ;
dfs2(son[u],f);
for(int i=h[u];~i;i=ne[i]){
int k=e[i];
if(k==fa[u])continue;
if(k==son[u])continue;
dfs2(k,k);
}
}
struct Node{
int l,r;
LL sum,add;
}tr[4*N];
void pu(int u){
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void pd(int u){
Node &root=tr[u],&left=tr[u<<1],&right=tr[u<<1|1];
if(root.add){
left.add+=root.add,right.add+=root.add;
left.sum+=(LL)(left.r-left.l+1)*root.add;
right.sum+=(LL)(right.r-right.l+1)*root.add;
root.add=0;
}
}
void build(int u,int l,int r){
tr[u]={l,r,0,0};
if(l==r){
tr[u].sum=wt[l];
return ;
}
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pu(u);
}
void modify(int u,int l,int r,int k){
if(tr[u].l>=l&&tr[u].r<=r){
tr[u].sum+=(LL)(tr[u].r-tr[u].l+1)*k;
tr[u].add+=k;
return ;
}
pd(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid)modify(u<<1,l,r,k);
if(r>mid)modify(u<<1|1,l,r,k);
pu(u);
}
LL query(int u,int l,int r){
if(tr[u].l>=l&&tr[u].r<=r)return tr[u].sum;
pd(u);
int mid=tr[u].l+tr[u].r>>1;
LL res=0;
if(l<=mid)res+=query(u<<1,l,r);
if(r>mid)res+=query(u<<1|1,l,r);
return res;
}
void add_path(int u,int v,int k){
while(p[u]!=p[v]){
if(dep[p[u]]<dep[p[v]])swap(u,v);
modify(1,dfn[p[u]],dfn[u],k);
u=fa[p[u]];
}
if(dep[u]<dep[v])swap(u,v);
modify(1,dfn[v],dfn[u],k);
}
void add_tree(int u,int k){
modify(1,dfn[u],dfn[u]+sz[u]-1,k);
}
LL query_path(int u,int v){
LL res=0;
while(p[u]!=p[v]){
if(dep[p[u]]<dep[p[v]])swap(u,v);
res+=query(1,dfn[p[u]],dfn[u]);
u=fa[p[u]];
}
if(dep[u]<dep[v])swap(u,v);
res+=query(1,dfn[v],dfn[u]);
return res;
}
LL query_tree(int u){
return query(1,dfn[u],dfn[u]+sz[u]-1);
}
int main()
{
ios::sync_with_stdio(0);
memset(h, -1, sizeof h);
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
cin>>m;
while(m--){
int op,u,v,k;
cin>>op;
if(op==1){
cin>>u>>v>>k;
add_path(u,v,k);
}
else if(op==2){
cin>>u>>k;
add_tree(u,k);
}
else if(op==3){
cin>>u>>v;
cout<<query_path(u,v)<<endl;
}
else{
cin>>u;
cout<<query_tree(u)<<endl;
}
}
}
浙公网安备 33010602011771号