Problem

Description

傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了。 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决。 整个地图是一个树结构,一共有 $n$块空地,这些空地被 $n-1$条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来。

在游戏中,幽香可能在空地上增加或者减少一些军队。同时,幽香可以在一个空地上放置一个补给站。 如果补给站在点 $u$ 上,并且空地 $v$上有 $d_v$ 个单位的军队,那么幽香每天就要花费 $d_v \times \text{dist}(u,v)$的金钱来补给这些军队。由于幽香需要补给所有的军队,因此幽香总共就要花费为 $\sum (d_v \times \text{dist}(u,v))$(其中$1 \leq v \leq N$)的代价,$\text{dist}(u,v)dist$表示 $u$个 $v$ 在树上的距离(唯一路径的权和)。 因为游戏的规定,幽香只能选择一个空地作为补给站。在游戏的过程中,幽香可能会在某些空地上制造一些军队,也可能会减少某些空地上的军队,进行了这样的操作以后,出于经济上的考虑,幽香往往可以移动他的补给站从而省一些钱。但是由于这个游戏的地图是在太大了,幽香无法轻易的进行最优的安排,你能帮帮她吗? 你可以假定一开始所有空地上都没有军队。

Input

第一行两个数 n和 Q分别表示树的点数和幽香操作的个数,其中点从1到n标号。

接下来 n-1 行,每行三个正整数 a,b,c,表示a和b之间有一条边权为c的边。

接下来 Q 行,每行两个数 u,e,表示幽香在点 u上放了 e单位个军队(如果 e<0,就相当于是幽香在 u上减少了 |e| 单位个军队,说白了就是$d_u←d_u+e$)。

数据保证任何时刻每个点上的军队数量都是非负的。

Output

对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。

Sample Input

10 5
1 2 1
2 3 1
2 4 1
1 5 1
2 6 1
2 7 1
5 8 1
7 9 1
1 10 1
3 1
2 1
8 1
3 1
4 1

Sample Output

0
1
4
5
6

HINT

对于所有数据,$1\le c\le 10^3$,$0\le |e| \le 10^30$,$1\le n\le10^5$ ,$1\le Q\le10^5$

非常神奇的是,对于所有数据,这棵树上的点的度数都不超过 20。

Solution

Analysis

考虑贪心,如果一个父子关系的点儿子比父亲优,那么答案一定在儿子方向(想想为什么,凸函数性质)

但是这样很糟糕,我们可能会变成$O(n)$。

考虑点分树,点分树保证了树高$log(n)$,那我们考虑如果一个点优就往这个点所在的子树的重心转移。

Attention

注意点分树上信息的维护(不具有直接父子传递性)

Code

$O(nlog^3n)$的垃圾代码

//Code by Enderturtle
#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define repe(i,a) for(register int i=head[a];i;i=e[i].nxt)
#define il inline
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
typedef long long ll;
using namespace std;
il void filejudge(){
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
il int read(){
    int x=0;bool f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=0;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return f?x:-x;
}
/*----- head end -----*/
const int N=100010;
int n;
struct Edge{ int v,w,nxt;} e[N<<1];int head[N],tot;
il void add_edge(int u,int v,int w){ e[++tot]=(Edge){v,w,head[u]};head[u]=tot;}
il void link(int u,int v,int w){ add_edge(u,v,w),add_edge(v,u,w);}
namespace slpf{
    int sz[N],fa[N],top[N],son[N];ll dep[N];
    il void dfs1(int u,int f){
        fa[u]=f;sz[u]=1;
        repe(i,u){
            int v=e[i].v;
            if(v==f) continue;
            dep[v]=dep[u]+e[i].w;
            dfs1(v,u);
            sz[u]+=sz[v];
            if(sz[v]>sz[son[u]]) son[u]=v;
        }
    }
    il void dfs2(int u,int topf){
        top[u]=topf;
        if(!son[u]) return;
        dfs2(son[u],topf);
        repe(i,u){
            int v=e[i].v;
            if(v==fa[u] || v==son[u]) continue;
            dfs2(v,v);
        }
    }
    il int lca(int u,int v){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            u=fa[top[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        return u;
    }
    il ll getdis(int u,int v){
        return dep[u]+dep[v]-2ll*dep[lca(u,v)];
    }
    il void init(){ dfs1(1,1);dfs2(1,1);}
}using slpf::getdis;
Edge g[N<<1];int nhead[N],ntot;
il void n_add_edge(int u,int v,int w){ g[++ntot]=(Edge){v,w,nhead[u]};nhead[u]=ntot;}
int fa[N],sz[N],mx[N],treesz,root;bool vis[N];
il void getsz(int u,int f){
    sz[u]=1;
    repe(i,u){
        int v=e[i].v;
        if(v==f || vis[v]) continue;
        getsz(v,u);
        sz[u]+=sz[v];
    }
//    cerr<<u<<' '<<sz[u]<<endl;
}
il void getroot(int u,int f){
//    cerr<<u<<' '<<f<<endl;
    mx[u]=0;
    repe(i,u){
        int v=e[i].v;
        if(v==f || vis[v]) continue;
        getroot(v,u);
        mx[u]=max(mx[u],sz[v]);
    }
    mx[u]=max(mx[u],treesz-mx[u]);
//    cerr<<mx[u]<<endl;
    if(mx[u]<mx[root]) root=u;
}
il void nxtroot(int u,int f){
    getsz(u,f);
    treesz=sz[u];root=0;
    getroot(u,f);
}
ll sum[N],sum_dis[N],sum_f[N];
il void modify(int u,int w){
    sum[u]+=w;
    int now=u;
    for(;fa[u]!=0;u=fa[u]){
        int f=fa[u];
        ll len=getdis(now,f);
        sum[f]+=w;
        sum_dis[f]+=1ll*w*len;
        sum_f[u]+=1ll*w*len;
    }
}
il ll calc(int u){
    ll res=sum_dis[u];
    int now=u;
    for(;fa[u]!=0;u=fa[u]){
        int f=fa[u];
        ll len=getdis(now,f);
        res+=(sum[f]-sum[u])*len;
        res+=(sum_dis[f]-sum_f[u]);
    }
    return res;
}
ll ans;
il void solve(ll u){
    ans=calc(u);
//    cerr<<u<<' '<<ans<<endl;
    for(register int i=nhead[u];i;i=g[i].nxt){
        int v=g[i].v,w=g[i].w;
        ll tmp=calc(w);
//        cerr<<w<<' '<<tmp<<endl;
        if(tmp<ans){ solve(v);return;}
    }
}
il void pre(int u){
    vis[u]=1;
    repe(i,u){
        int v=e[i].v;
        if(vis[v]) continue;
        nxtroot(v,u);
        fa[root]=u;
        n_add_edge(u,root,v);
        pre(root);
    }
}
int main(){
    n=read();int Q=read();
    rep(i,2,n){ int u=read(),v=read(),w=read();link(u,v,w);}
    mx[0]=n+1;
    slpf::init();
    int RT;
    nxtroot(1,1);
    RT=root;
    pre(root);
//    rep(i,1,n) cerr<<fa[i]<<' ';
    while(Q--){
        int u=read(),e=read();
        modify(u,e);
    //    rep(i,1,n) cerr<<sum[i]<<' '<<sum_dis[i]<<endl;
        solve(RT);
        printf("%lld\n",ans);
    }
    return 0;
}

一个好奇的人