#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=100010;
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
struct zyx{
int to,w;
};
vector<zyx> e[N];
int dfn[N],rnk[N],dis[N],sz[N],fz[N],son[N],top[N];
int cnt,n,Q;
struct SegementTree{
int w[N<<2];//w叶子记录子树大小,维护的是子树大小max
int sum[N<<2],lazy[N<<2];
int edge[N<<2];//记录边权的
void pushup(int u){
w[u]=max(w[u*2],w[u*2+1]);
sum[u]=sum[u*2]+sum[u*2+1];
}
void pushdown(int u){
if(!lazy[u])return;
w[u*2]+=lazy[u];
w[u*2+1]+=lazy[u];
lazy[u*2]+=lazy[u];
lazy[u*2+1]+=lazy[u];
sum[u*2]+=lazy[u]*edge[u*2];
sum[u*2+1]+=lazy[u]*edge[u*2+1];
lazy[u]=0;
}
void build(int u,int l,int r){
if(l==r){
edge[u]=dis[rnk[l]]-dis[fz[rnk[l]]];
w[u]=0;
return;
}
int mid=(l+r)>>1;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
edge[u]=edge[u*2]+edge[u*2+1];
//这里难道需要pushup edge 吗?
}
void add(int u,int l,int r,int x,int y,int k){
if(x<=l&&r<=y){
w[u]+=k;
sum[u]+=k*edge[u];
lazy[u]+=k;
return;
}
pushdown(u);
int mid=(l+r)>>1;
if(x<=mid)add(u*2,l,mid,x,y,k);
else add(u*2+1,mid+1,r,x,y,k);
pushup(u);
}
int query(int u,int l,int r,int x,int y){
if(x<=l&&r<=y){
return sum[u];
}
int mid=(l+r)>>1;
pushdown(u);
int res=0;
if(x<=mid)res+=query(u*2,l,mid,x,y);
if(y>mid)res+=query(u*2+1,mid+1,r,x,y);
return res;
}
int search(){
int u=1,l=1,r=n;
while(l<r){
int mid=(l+r)>>1;
pushdown(u);
if(w[u*2+1]*2>=w[1])u=u*2+1,l=mid+1;
else u=u*2,r=mid;
}
return rnk[l];
}
//上面一部分是线段树上二分求重心
//下面一部分需要实现的是
//区间加,区间 a*b 的和,其中 只改变 a
void ADD(int now,int e){
while(now!=0){
add(1,1,n,dfn[top[now]],dfn[now],e);
now=fz[top[now]];
}
return;
}
int QUE(int now){
int res=0;
while(now!=0){
res+=query(1,1,n,dfn[top[now]],dfn[now]);
now=fz[top[now]];
}
return res;
}
}T;
void dfs1(int now,int fa){
sz[now]=1;
fz[now]=fa;
for(int i=0;i<(int)e[now].size();i++){
int to=e[now][i].to;
if(to==fa)continue;
dis[to]=dis[now]+e[now][i].w;
dfs1(to,now);
sz[now]+=sz[to];
if(sz[son[now]]<sz[to])son[now]=to;
}
}
void dfs2(int now,int topf){
dfn[now]=++cnt;
rnk[cnt]=now;
top[now]=topf;
if(!son[now])return;
dfs2(son[now],topf);
for(int i=0;i<(int)e[now].size();i++){
int to=e[now][i].to;
if(to==son[now]||to==fz[now])continue;
dfs2(to,to);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
n=read(),Q=read();
for(int i=1;i<n;i++){
int u=read(),v=read(),w=read();
e[u].push_back((zyx){v,w});
e[v].push_back((zyx){u,w});
}
dfs1(1,0);
dfs2(1,1);
T.build(1,1,n);
int dis_y_root=0,sum_e_y=0;
for(int i=1;i<=Q;i++){
int u=read(),e=read();
T.ADD(u,e);
dis_y_root+=e*dis[u];
sum_e_y+=e;
int zx=T.search();
// cout<<"重心为"<<zx<<'\n';
// cout<<"第一项为"<<dis[zx]*sum_e_y<<'\n';
// cout<<"第二项为"<<dis_y_root<<'\n';
// cout<<"QUE="<<T.QUE(zx)<<'\n';
cout<<dis[zx]*sum_e_y+dis_y_root-2*T.QUE(zx)<<'\n';
}
return 0;
}
思路是区间 max 线段树上二分求重心,叶子节点记录子树大小。后面树剖维护答案。