Meaning of the questions: Given a tree, there are $ m $ operations.
Operation 0: $, $ weight is set to a path adding S $ $ (p, q) $ v $
Operation 1: Given a set of points $ T $, seeking of $ T $ and sets right and $ S $ path having the intersection, and (that is, if the path $ I $ and $ T $ intersect, generated $ v_ { i} $ contributions)
Data range: path length $ \ leqslant 20 1 \ leqslant n $, $, m \ leqslant 10 ^ 5 $
Tree and right chain is to find our set of points of $ T $ If the path length is 0 (i.e., S $ $ points in all) and the words.
The DFS can be used to maintain order + Fenwick tree.
An important property is that the tree between any two points if after $ I $ points will then go through $ i-1 $ edges, the number of edges is always points -1.
Then the next step is especially God:
For the newly added path: the point on the path adding weights plus side opposite of weights.
If you find a communication path from this block and set it must have elapsed points and $ I $ $ i-1 $ edges.
That is equal to a constant number of edges points - 1, which achieved only once the effect of the contribution.
For the right to maintain a point to the root and, the way we use DFS order + tree array.
#include <vector> #include <cstdio> #include <set> #include <cstring> #include <string> #include <algorithm> #define N 200007 #define ll long long using namespace std; void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); freopen(out.c_str(),"w",stdout); } struct BIT { ll C[N]; int lowbit(int t) { return t&(-t); } void update(int x,int v) { while(x<N) { C[x]+=(ll)v; x+=lowbit(x); } } ll query(int x) { ll tmp=0; while(x>0) { tmp+=C[x]; x-=lowbit(x); } return tmp; } }tree; int tot; int n,m,L; int edges; int dfn; int hd[N]; int to[N<<1]; int nex[N<<1]; int top[N]; int son[N]; int size[N]; int dep[N]; int A[N]; int fa[N]; int st[N]; int ed[N]; int Fa[N]; vector<int>G[N]; bool cmp(int a,int b) { return st[a]<st[b]; } void add(int u,int v) { nex[++edges]=hd[u]; hd[u]=edges; to[edges]=v; } void dfs1(int u,int ff) { fa[u]=ff; size[u]=1; dep[u]=dep[ff]+1; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v==ff) { continue; } dfs1(v,u); size[u]+=size[v]; if(size[v]>size[son[u]]) { son[u]=v; } } } void dfs2(int u,int tp) { top[u]=tp; if(son[u]) { dfs2(son[u],tp); } for(int i=hd[u];i;i=nex[i]) { if(to[i]!=fa[u]&&to[i]!=son[u]) { dfs2(to[i],to[i]); } } } int LCA(int x,int y) { while(top[x]!=top[y]) { dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; } return dep[x]<dep[y]?x:y; } // 到根的权和 ll Sum(int x) { return tree.query(st[x]); } void build(int u) { for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v==fa[u]) { continue; } ++tot; Fa[tot]=u; Fa[v]=tot; G[u].push_back(tot); G[tot].push_back(v); build(v); } } void dfs(int u) { st[u]=++dfn; for(int i=0;i<G[u].size();++i) { int v=G[u][i]; // printf("%d %d\n",u,v); dfs(v); } ed[u]=dfn; } int main() { setIO("tree"); int i,j; scanf("%d%d%d",&n,&m,&L); for(i=1;i<n;++i) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs1(1,0); dfs2(1,1); tot=n; build(1); dfs(1); while(m--) { int op; scanf("%d",&op); if(op==0) { int p,q,v,d=1; scanf("%d%d%d",&p,&q,&v); int lca=LCA(p,q); while(p!=lca) { tree.update(st[p],d*v); tree.update(ed[p]+1,-d*v); d*=-1; p=Fa[p]; } d=1; while(q!=lca) { tree.update(st[q],d*v); tree.update(ed[q]+1,d*v); d*=-1; q=Fa[q]; } tree.update(st[lca],v); tree.update(ed[lca]+1,-v); } else { int a,cnt=0; scanf("%d",&a); for(i=1;i<=a;++i) { scanf("%d",&A[++cnt]); } scanf("%d",&a); for(i=1;i<=a;++i) { scanf("%d",&A[++cnt]); } sort(A+1,A+1+cnt,cmp); int lca=A[1]; for(i=2;i<=cnt;++i) { lca=LCA(lca,A[i]); } ll ans=0; for(i=1;i<=cnt;++i) { ans+=Sum(A[i])-Sum(Fa[lca]); } for(i=2;i<=cnt;++i) { ans-=Sum(LCA(A[i],A[i-1]))-Sum(Fa[lca]); } printf("%lld\n",ans); } } return 0; }