如果暴力维护,每次询问时需要对所有孩子做计算
考虑通过树剖来平衡修改与询问的时间,询问时计算重链和父树,轻链的贡献预先维护好,修改时则需要修改可能影响的轻链贡献,因为某个点到根的路径上轻重交替只有 (O(log n)) 个,所以只需要修改这么多次,于是复杂度有保证,树状数组维护子树即可
我真是个憨憨,打错树剖调一晚,地上蛙血一大摊
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6+5;
int ar[N]; // index: 1 ~ N
int lowbit(int t) { return t & (-t); }
void add(int i, int v) {
for (; i < N; ar[i] += v, i += lowbit(i));
}
void add(int i, int j, int v) {
add (j+1, -v);
add (i, v);
}
int sum(int i) {
int s = 0;
for (; i > 0; s += ar[i], i -= lowbit(i));
return s;
}
vector <pair<int,int> > g[N];
int n,m,t1,t2,t3,pos;
int fa[N],siz[N],f[N],cnt[N],wson[N],len[N],dfn[N],top[N],ind,tot;
void dfs1(int p) {
siz[p]=1;
for(pair<int,int> pr:g[p]) {
int q=pr.first, w=pr.second;
if(q==fa[p]) continue;
fa[q]=p;
len[q]=w;
dfs1(q);
siz[p]+=siz[q];
if(siz[q]>siz[wson[p]]) wson[p]=q;
}
}
void dfs2(int p) {
dfn[p]=++ind;
if(wson[p]) {
top[wson[p]]=top[p];
dfs2(wson[p]);
}
for(pair<int,int> pr:g[p]) {
int q=pr.first, w=pr.second;
if(q==fa[p]) continue;
if(q==wson[p]) continue;
top[q]=q;
dfs2(q);
}
}
void modify(int v,int x) {
cnt[v]+=x;
//v=fa[v];
while(v) {
int t=top[v];
add(dfn[t],dfn[v],x);
f[fa[t]]+=x*len[t];
v=fa[t];
}
f[0]=0;
}
int query(int p) {
int ans=0;
ans+=sum(dfn[wson[p]])*len[wson[p]];
ans+=f[p];
ans+=len[p]*(tot-sum(dfn[p]));
//cout<<sum(dfn[wson[p]])<<"*"<<len[wson[p]]<<" + "<<
//f[p]<<" + "<<len[p]<<"*"<<(tot-sum(dfn[p]))<<" = "<<ans<<endl;
return ans;
}
signed main() {
scanf("%lld",&n);
for(int i=1;i<n;i++) {
scanf("%lld%lld%lld",&t1,&t2,&t3);
g[t1].push_back(make_pair(t2,t3));
g[t2].push_back(make_pair(t1,t3));
}
dfs1(1);
top[1]=1;
dfs2(1);
pos=1;
scanf("%lld",&m);
for(int i=1;i<=m;i++) {
scanf("%lld%lld",&t1,&t2);
if(t1==1) scanf("%lld",&t3), tot+=t3;
if(t1==1) modify(t2,t3);
else pos=t2;
printf("%lld
",query(pos));
}
}